home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
DCLAP 6d
/
dclap6d
/
network
/
nsclilib
/
ni_msg.c
< prev
next >
Wrap
Text File
|
1996-07-05
|
126KB
|
4,248 lines
/*
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
* National Center for Biotechnology Information
*
* This software/database is a "United States Government Work" under the
* terms of the United States Copyright Act. It was written as part of
* the author's official duties as a United States Government employee and
* thus cannot be copyrighted. This software/database is freely available
* to the public for use. The National Library of Medicine and the U.S.
* Government have not placed any restriction on its use or reproduction.
*
* Although all reasonable efforts have been taken to ensure the accuracy
* and reliability of the software and data, the NLM and the U.S.
* Government do not and cannot warrant the performance or results that
* may be obtained by using this software or data. The NLM and the U.S.
* Government disclaim all warranties, express or implied, including
* warranties of performance, merchantability or fitness for any particular
* purpose.
*
* Please cite the author in any work or product based on this material.
*
* ===========================================================================
*
* File Name: ni_msg.c
*
* Author: Beatty, Gish, Epstein
*
* Version Creation Date: 1/1/92
*
* $Revision: 4.0 $
*
* File Description:
* This file consists mostly of functions for creating, destroying, reading,
* and writing message structures. It also contains the high-level functions
* for reading or writing a message, as well as the lowest-level functions
* which are read, write, and error 'hooks' for the ASN library.
*
* Modifications:
* --------------------------------------------------------------------------
* Date Name Description of modification
* ------- ---------- -----------------------------------------------------
* 5/01/92 Epstein Added extensive in-line commentary, and removed all tabs
* 5/01/92 Epstein Modified to support un-blocked reads, by storing state
* information and returning to the caller.
* 5/11/92 Epstein Changed MsgBuild() to free memory in the event of
* an invalid message type; fixed MsgDestroy() to
* return -1 rather than NULL (NULL is the wrong type);
* added logic to allow the dispatcher to update the
* CONID file when the value of "conid" is incremented
* 6/18/92 Epstein Added AsnIoSetBufsize() for write socket, to improve
* network throughput.
* 6/22/92 Epstein Changed all NI_AsnRead() and NI_AsnWrite() error return
* codes to be the negative of the absolute value of errno,
* because errno's can be negative on Macintoshes.
* 7/10/92 Epstein Changed MsgSaveData() to set the current index
* (mh->cur_index) to match the number of queued bytes;
* this avoids unintentional re-reading of queued data
* unless a read fails.
* 2/12/93 Epstein Add an argument to MsgMakeHandle() to indicate whether
* or not a socket should be created.
* 2/19/93 Epstein Add PC-NFS 4.0 support.
* 2/24/93 Epstein Fix memory leak
* 3/08/93 Epstein Add optional client platform to service request
* 3/11/93 Epstein Add "is-alternate-list" boolean to dispatcher-list,
* to make it easier for a dispatcher-monitor-client
* to distinguish between primary and backup dispatchers.
* 3/23/93 Epstein Change platform conditional-compilation to include
* the NETP_INET_ prefix, add VMS/TGV support.
* 4/02/93 Epstein Remember to initialize conid to a known value ... this
* avoids clients connecting with all sorts of wild conid
* values.
* 4/02/93 Epstein Add preliminary WinSock support.
* 4/13/93 Epstein Add subSet fields to toolset to support catalog
* filtering by dispatcher.
* 4/21/93 Schuler Removed (IoFuncType) typecast on calls to AsnIoNew()
* in order to enable compile-time type checking.
* 4/21/93 Schuler Changed implementation of NI_AsnNew(), NI_AsnWrite(), and
* NI_ASNIOError() to use LIBCALLBACK calling convention.
* 4/21/93 Epstein Fix MsgBuild() return error (was incorrectly returning
* FALSE instead of NULL).
* 5/07/93 Epstein Fixup NI_SetBlocking() and NI_SetNonBlocking(), which
* had been backwards. Also add Wollongong (TWG) support,
* and use INVALID_SOCKET #define, per WinSock spec.
* 5/25/93 Epstein Add regional support, and add application ID to
* service request.
* 5/27/93 Epstein Provide separate error code for ASN.1 dynamic object
* loader failure, try to do separate PeekMessage, etc.
* code for WinSock in the never-ending battle to fix
* scrollbar behavior under WinSock.
* 5/28/93 Epstein Re-work Disable-vibrant code to use new pragmatic
* "Gestalt" functions, rather than making explicit
* calls into Vibrant. This decouples Network Services
* from Vibrant.
* 6/02/93 Epstein Fixup sys_errlist references to correctly use new
* SOCK_INDEX_ERRNO macro, to accomodate yet another
* WinSock peculiarity.
* 6/07/93 Epstein Use new timer mechanism to support "hung timeout";
* also add new function MsgSetTimeoutHooks().
* Also add missing revision history, derived from
* RCS file.
* 6/09/93 Epstein Added activity hook to report network activity back
* to an application.
* 6/15/93 Epstein Fix long-standing WinSock scrolling problem, by changing
* NI_poll_select() to refrain from processing
* WM_LBUTTONUP messages. For some reason, reading these
* messages off the queue and processing them resulted
* in a failure to correctly interpret the WM_LBUTTONUP
* message as an "end scrolling" message.
* Also clean-up Windows compilation warnings.
* 6/17/93 Epstein Temporarily change NI_SetNonBlocking() to provide
* incorrect (blocking!) semantics for TWG. This must
* be fixed at a later date.
* 6/22/93 Epstein Support UCX, although NI_SetNonBlocking() and
* NI_SetBlocking() are currently completely unsupported.
* This should be fixed at a later date if it turns out
* that UCX actually supports these features.
* 8/09/93 Epstein Remove annoying cursor modification, except for NEWT,
* where it may be necessary.
*01/21/94 Schuler Calls to Yield() bracketed by #ifdef WIN61/#endif
*01/28/94 Schuler Replaced "OS_MAC" with "NETP_INET_MACTCP"
*01/28/94 Schuler Defined THIS_MODULE and THIS_FILE
*02/14/94 Epstein Added encryption support
*02/16/94 Epstein Replaced Gestalt calls with SetAppProperty()
*02/24/94 Epstein Move des-key from dispinfo to login to allow ncbid
* to send a DES key to dispatcher. Also performed some
* cleanup.
*06/08/94 Epstein Add messages needed for SOCKS support
*06/15/94 Epstein Add parameter to MsgWrite(), and add server-ip to
* service request, both to accomodate SOCKS.
*12/06/94 Epstein Added connectDelay, adminInfo and motd field to
* client<->Dispatcher communication. Also populated
* the priority field in the Catalog.
*12/21/94 Epstein Make use of new socket instrumentation
* ==========================================================================
*
*
* RCS Modification History:
* $Log: ni_msg.c,v $
* Revision 4.0 1995/07/26 13:56:32 ostell
* force revision to 4.0
*
* Revision 1.37 1995/05/24 12:08:54 epstein
* add support for tracking of how many times a client IP has used a service within a time interval
*
* Revision 1.36 95/05/17 17:52:39 epstein
* add RCS log revision history
*
*/
extern char * g_nsclient_module;
#define THIS_MODULE g_nsclient_module
static char * _this_file = __FILE__;
#define THIS_FILE _this_file
#include <ncbi.h>
#include "ni_msg.h"
#include "ni_asn.h" /* produced by ASNTOOL */
/* macros */
#if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
/* cooperation may be required with Vibrant to avoid runaway scrollbars */
#define DisabVibrant() { Nlm_SetAppProperty("disable_vibrant", "1"); SetHourGlass(); }
#define EnabVibrant() { Nlm_RemoveAppProperty("disable_vibrant"); PopHourGlass(); }
#else
#define DisabVibrant()
#define EnabVibrant()
#endif /* NETP_INET_NEWT */
static NIAckPtr readACK PROTO((void));
static void writeACK PROTO((NIAckPtr ackp));
static NINackPtr readNACK PROTO((void));
static void writeNACK PROTO((NINackPtr nackp));
static NILoginPtr readLOGIN PROTO ((void));
static void writeLOGIN PROTO((NILoginPtr loginp));
static NISvcListPtr readSVC_LIST PROTO ((void));
static void writeSVC_LIST PROTO((NISvcListPtr svclistp));
static NISvcReqPtr readSVC_REQUEST PROTO ((void));
static void writeSVC_REQUEST PROTO((NISvcReqPtr svcreqp));
static NISvcRespPtr readSVC_RESPONSE PROTO ((void));
static void writeSVC_RESPONSE PROTO((NISvcRespPtr svcrespp));
static NICmdPtr readCOMMAND PROTO ((void));
static void writeCOMMAND PROTO((NICmdPtr cmdp));
static NIPreRespPtr readPRE_RESPONSE PROTO ((void));
static void writePRE_RESPONSE PROTO((NIPreRespPtr prp));
static NIAcctPtr readACCT PROTO ((void));
static void writeACCT PROTO((NIAcctPtr accp));
static NICatalogPtr readCATALOG PROTO ((void));
static void writeCATALOG PROTO((NICatalogPtr catp));
static int readRequest PROTO ((ReqPtr rp));
static void writeRequest PROTO((ReqPtr reqp));
static int readUid PROTO ((NI_UidPtr uid));
static void writeUid PROTO((NI_UidPtr uidp));
static int readService PROTO ((NISvcPtr svcp));
static void writeService PROTO((NISvcPtr svcp));
static int readResource PROTO ((NIResPtr resp));
static void writeResource PROTO((NIResPtr resp));
static int readRegion PROTO ((NIRegionPtr regp));
static void writeRegion PROTO((NIRegionPtr regp));
static int readToolset PROTO ((NIToolsetPtr tsp));
static void writeToolset PROTO((NIToolsetPtr tsp));
static int readPubKey PROTO ((NIPubKeyPtr pubkey));
static void writePubKey PROTO((NIPubKeyPtr pubkey));
static int readDispInfo PROTO ((NIDispInfoPtr dip));
static void writeDispInfo PROTO((NIDispInfoPtr dip));
static Boolean InitMsg PROTO((void));
static void WriteCleanup PROTO((CharPtr tmpbuf));
static Boolean MsgHaveSavedData PROTO((MHandPtr mh));
static void MsgSaveData PROTO((MHandPtr mh, CharPtr buf,
Uint2 len));
static int MsgReadSavedData PROTO((MHandPtr mh,
CharPtr buf, Uint2 len));
static void MsgFreeSavedData PROTO((MHandPtr mh));
static void SetHourGlass PROTO((void));
static void PopHourGlass PROTO((void));
/* VARS */
Uint4 conid = 1; /* globally unique connection ID counter */
Jumpbuf ni_env; /* saved environment for LongJump (servers only) */
static AsnTypePtr atp;
static AsnIoPtr aip;
/* FUNCTIONS */
/******************************************************************************/
/* */
/* Functions for creating, destroying, reading, and writing message structures*/
/* */
/******************************************************************************/
/************************************ ACK *************************************/
NIAckPtr
NI_MakeMsgAck(void)
{
NIAckPtr ap;
ap = (NIAckPtr) MemNew(sizeof(NIAck));
ap->seqno = 0;
ap->dispinfo = NULL;
ap->adminInfo = NULL;
ap->motd = NULL;
return ap;
} /* NI_MakeMsgAck */
Int2
NI_DestroyMsgAck(NIAckPtr mp)
{
if (mp == NULL)
return 1;
if (mp->dispinfo != NULL)
{
NI_DestroyDispInfo(mp->dispinfo);
}
if (mp->adminInfo != NULL)
{
MemFree(mp->adminInfo);
}
if (mp->motd != NULL)
{
MemFree(mp->motd);
}
MemFree(mp);
return 0;
} /* NI_MakeMsgAck */
static NIAckPtr
readACK(void)
{
DataVal value;
NIAckPtr ackp;
ackp = NI_MakeMsgAck();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* seqno */
goto AckFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AckFail;
ackp->seqno = value.intvalue;
atp = AsnReadId(aip, amp, atp);
if (atp == MSG_ACK_disp_info) {
if (AsnReadVal(aip, atp, &value) < 0)
goto AckFail;
ackp->dispinfo = NI_MakeDispInfo();
if (readDispInfo(ackp->dispinfo) < 0)
goto AckFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto AckFail;
}
if (atp == MSG_ACK_admin_info) {
if (AsnReadVal(aip, atp, &value) < 0)
goto AckFail;
ackp->adminInfo = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto AckFail;
}
if (atp == MSG_ACK_motd) {
if (AsnReadVal(aip, atp, &value) < 0)
goto AckFail;
ackp->motd = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto AckFail;
}
if (atp != MESSAGE_ack)
goto AckFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AckFail;
return ackp;
AckFail:
NI_DestroyMsgAck(ackp);
return NULL;
} /* readACK */
static void
writeACK(NIAckPtr ackp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_ack);
value.intvalue = (Int4) ackp->seqno;
AsnWrite(aip, MSG_ACK_seqno, &value);
if (ackp->dispinfo != NULL) {
AsnStartStruct(aip, MSG_ACK_disp_info);
writeDispInfo(ackp->dispinfo);
AsnEndStruct(aip, MSG_ACK_disp_info);
}
if (ackp->adminInfo != NULL) {
value.ptrvalue = (Pointer) ackp->adminInfo;
AsnWrite(aip, MSG_ACK_admin_info, &value);
}
if (ackp->motd != NULL) {
value.ptrvalue = (Pointer) ackp->motd;
AsnWrite(aip, MSG_ACK_motd, &value);
}
AsnEndStruct(aip, MESSAGE_ack);
} /* writeACK */
/************************************ NACK ***********************************/
NINackPtr
NI_MakeMsgNack(void)
{
NINackPtr np;
np = (NINackPtr) MemNew(sizeof(NINack));
np->seqno = 0;
np->reason = NULL;
np->dispinfo = NULL;
return np;
} /* NI_MakeMsgNack */
Int2
NI_DestroyMsgNack(NINackPtr mp)
{
if (mp == NULL)
return 1;
if (mp->reason != NULL)
MemFree(mp->reason);
if (mp->dispinfo != NULL)
NI_DestroyDispInfo(mp->dispinfo);
MemFree(mp);
return 0;
} /* NI_DestroyMsgNack */
static NINackPtr
readNACK(void)
{
DataVal value;
NINackPtr nackp;
nackp = NI_MakeMsgNack();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* seqno */
goto NackFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto NackFail;
nackp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* code */
goto NackFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto NackFail;
nackp->code = (NI_Error) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == MSG_NACK_reason) { /* reason */
if (AsnReadVal(aip, atp, &value) < 0)
goto NackFail;
nackp->reason = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto NackFail;
}
if (atp == MSG_NACK_disp_info) {
if (AsnReadVal(aip, atp, &value) < 0)
goto NackFail;
nackp->dispinfo = NI_MakeDispInfo();
if (readDispInfo(nackp->dispinfo) < 0)
goto NackFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto NackFail;
}
if (atp != MESSAGE_nack)
goto NackFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto NackFail;
return nackp;
NackFail:
NI_DestroyMsgNack(nackp);
return NULL;
} /* readNACK */
static void
writeNACK(NINackPtr nackp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_nack);
value.intvalue = (Int4) nackp->seqno;
AsnWrite(aip, MSG_NACK_seqno, &value);
value.intvalue = (Int4) nackp->code;
AsnWrite(aip, MSG_NACK_code, &value);
if (nackp->reason != NULL) {
value.ptrvalue = (Pointer) nackp->reason;
AsnWrite(aip, MSG_NACK_reason, &value);
}
if (nackp->dispinfo != NULL) {
AsnStartStruct(aip, MSG_NACK_disp_info);
writeDispInfo(nackp->dispinfo);
AsnEndStruct(aip, MSG_NACK_disp_info);
}
AsnEndStruct(aip, MESSAGE_nack);
}
/************************************ LOGIN ***********************************/
NILoginPtr
NI_MakeMsgLogin(void)
{
NILoginPtr lp;
lp = (NILoginPtr) MemNew(sizeof(NILogin));
lp->seqno = 0;
lp->uid = NI_MakeUid();
lp->password = NULL;
lp->dispserialno = -1;
lp->encryptionDesired = FALSE;
lp->pubKey = NULL;
lp->desKey = NULL;
lp->connectDelay = -1;
return lp;
} /* NI_MakeMsgLogin() */
Int2
NI_DestroyMsgLogin(NILoginPtr lp)
{
if (lp == NULL)
return 1;
if (lp->uid != NULL)
NI_DestroyUid(lp->uid);
if (lp->password != NULL)
MemFree(lp->password);
if (lp->pubKey != NULL)
NI_DestroyPubKey(lp->pubKey);
if (lp->desKey != NULL)
BSFree(lp->desKey);
MemFree(lp);
return 0;
} /* NI_DestroyMsgLogin() */
static NILoginPtr
readLOGIN(void)
{
DataVal value;
NILoginPtr loginp;
loginp = NI_MakeMsgLogin();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* seqno */
goto LoginFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
loginp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_LOGIN_uid */
goto LoginFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
if (readUid(loginp->uid) < 0)
goto LoginFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* password ? */
goto LoginFail;
if (atp == MSG_LOGIN_password) {
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
loginp->password = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto LoginFail;
}
if (atp == MSG_LOGIN_disp_serial_no) {
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
loginp->dispserialno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto LoginFail;
}
if (atp == MSG_LOGIN_encryption_desired) {
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
loginp->encryptionDesired = value.boolvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto LoginFail;
}
if (atp == MSG_LOGIN_pub_key) {
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
loginp->pubKey = NI_MakePubKey();
if (readPubKey(loginp->pubKey) < 0)
goto LoginFail;
if ((atp = AsnReadId(aip,amp,atp)) == NULL)
goto LoginFail;
}
if (atp == MSG_LOGIN_des_key) {
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
loginp->desKey = (ByteStorePtr) value.ptrvalue;
if ((atp = AsnReadId(aip,amp,atp)) == NULL)
goto LoginFail;
}
if (atp == MSG_LOGIN_connect_delay) {
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
loginp->connectDelay = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto LoginFail;
}
if (atp != MESSAGE_login)
goto LoginFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto LoginFail;
return loginp;
LoginFail:
NI_DestroyMsgLogin(loginp);
return NULL;
} /* readLOGIN */
static void
writeLOGIN(NILoginPtr loginp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_login);
value.intvalue = (Int4) loginp->seqno;
AsnWrite(aip, MSG_LOGIN_seqno, &value);
AsnStartStruct(aip, MSG_LOGIN_uid);
writeUid(loginp->uid);
AsnEndStruct(aip, MSG_LOGIN_uid);
if (loginp->password != NULL) {
value.ptrvalue = (Pointer) loginp->password;
AsnWrite(aip, MSG_LOGIN_password, &value);
}
if (loginp->dispserialno >= 0) {
value.intvalue = loginp->dispserialno;
AsnWrite(aip, MSG_LOGIN_disp_serial_no, &value);
}
if (loginp->encryptionDesired) {
value.boolvalue = loginp->encryptionDesired;
AsnWrite(aip, MSG_LOGIN_encryption_desired, &value);
}
if (loginp->pubKey != NULL) {
AsnStartStruct(aip, MSG_LOGIN_pub_key);
writePubKey(loginp->pubKey);
AsnEndStruct(aip, MSG_LOGIN_pub_key);
}
if (loginp->desKey != NULL) {
value.ptrvalue = (Pointer) loginp->desKey;
AsnWrite(aip, MSG_LOGIN_des_key, &value);
}
if (loginp->connectDelay >= 0) {
value.intvalue = loginp->connectDelay;
AsnWrite(aip, MSG_LOGIN_connect_delay, &value);
}
AsnEndStruct(aip, MESSAGE_login);
} /* writeLOGIN */
/************************************ SVC_LIST ********************************/
NISvcListPtr
NI_MakeMsgSvclist(void)
{
NISvcListPtr sp;
sp = (NISvcListPtr) MemNew(sizeof(NISvcList));
sp->seqno = 0;
sp->toolset = NI_MakeToolset();
sp->knowsTracking = FALSE;
return sp;
} /* NI_MakeMsgSvclist */
Int2
NI_DestroyMsgSvclist(NISvcListPtr sp)
{
if (sp == NULL)
return 1;
if (sp->toolset != NULL)
NI_DestroyToolset(sp->toolset);
MemFree(sp);
return 0;
} /* NI_DestroyMsgSvclist */
static NISvcListPtr
readSVC_LIST(void)
{
DataVal value;
NISvcListPtr svclistp;
svclistp = NI_MakeMsgSvclist();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_LIST_seqno */
goto SvcListFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcListFail;
svclistp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_LIST_toollist */
goto SvcListFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcListFail;
if (readToolset(svclistp->toolset) < 0)
goto SvcListFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto SvcListFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcListFail;
if (atp == MSG_SVC_LIST_knows_tracking)
{
svclistp->knowsTracking = value.boolvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto SvcListFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcListFail;
}
if (atp != MESSAGE_svc_list)
goto SvcListFail;
return svclistp;
SvcListFail:
NI_DestroyMsgSvclist(svclistp);
return NULL;
} /* readSVC_LIST */
static void
writeSVC_LIST(NISvcListPtr svclistp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_svc_list);
value.intvalue = (Int4) svclistp->seqno;
AsnWrite(aip, MSG_SVC_LIST_seqno, &value);
AsnStartStruct(aip, MSG_SVC_LIST_toollist);
writeToolset(svclistp->toolset);
AsnEndStruct(aip, MSG_SVC_LIST_toollist);
if (svclistp->knowsTracking)
{
value.boolvalue = svclistp->knowsTracking;
AsnWrite(aip, MSG_SVC_LIST_knows_tracking, &value);
}
AsnEndStruct(aip, MESSAGE_svc_list);
} /* writeSVC_LIST */
/************************************ SVC_REQUEST *****************************/
NISvcReqPtr
NI_MakeMsgSvcreq(void)
{
NISvcReqPtr sp;
sp = (NISvcReqPtr) MemNew(sizeof(NISvcReq));
sp->seqno = 0;
sp->uid = NI_MakeUid();
sp->request = NI_MakeRequest();
sp->platform = NI_PLATFORM_UNKNOWN;
sp->applId = NULL;
sp->desKey = NULL;
sp->wantPreResponse = FALSE;
sp->server_ip = 0;
return sp;
} /* NI_MakeMsgSvcreq() */
Int2
NI_DestroyMsgSvcreq(NISvcReqPtr sp)
{
if (sp == NULL)
return 1;
if (sp->uid != NULL)
NI_DestroyUid(sp->uid);
if (sp->request != NULL)
NI_DestroyRequest(sp->request);
if (sp->applId != NULL)
MemFree(sp->applId);
if (sp->desKey != NULL)
BSFree (sp->desKey);
MemFree(sp);
return 0;
} /* NI_DestroyMsgSvcreq() */
static NISvcReqPtr
readSVC_REQUEST(void)
{
DataVal value;
NISvcReqPtr svcreqp;
svcreqp = NI_MakeMsgSvcreq();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_REQUEST_seqno */
goto SvcReqFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
svcreqp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_REQUEST_conid */
goto SvcReqFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
svcreqp->conid = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_REQUEST_uid */
goto SvcReqFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
if (readUid(svcreqp->uid) < 0)
goto SvcReqFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_REQUEST_request */
goto SvcReqFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
if (readRequest(svcreqp->request) < 0)
goto SvcReqFail;
if ((atp = AsnReadId(aip, amp, atp)) == MSG_SVC_REQUEST_platform) {
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
svcreqp->platform = (Uint4) value.intvalue;
atp = AsnReadId(aip, amp, atp);
}
if (atp == MSG_SVC_REQUEST_appl_id) {
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
svcreqp->applId = (CharPtr) value.ptrvalue;
atp = AsnReadId(aip, amp, atp);
}
if (atp == MSG_SVC_REQUEST_des_key) {
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
svcreqp->desKey = (ByteStorePtr) value.ptrvalue;
atp = AsnReadId(aip, amp, atp);
}
if (atp == SVC_REQUEST_want_pre_response) {
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
svcreqp->wantPreResponse = value.boolvalue;
atp = AsnReadId(aip, amp, atp);
}
if (atp == MSG_SVC_REQUEST_server_ip) {
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
svcreqp->server_ip = value.intvalue;
atp = AsnReadId(aip, amp, atp);
}
if (atp != MESSAGE_svc_request)
goto SvcReqFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcReqFail;
return svcreqp;
SvcReqFail:
NI_DestroyMsgSvcreq(svcreqp);
return NULL;
} /* readSVC_REQUEST */
static void
writeSVC_REQUEST(NISvcReqPtr svcreqp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_svc_request);
value.intvalue = (Int4) svcreqp->seqno;
AsnWrite(aip, MSG_SVC_REQUEST_seqno, &value);
value.intvalue = (Int4) svcreqp->conid;
AsnWrite(aip, MSG_SVC_REQUEST_conid, &value);
AsnStartStruct(aip, MSG_SVC_REQUEST_uid);
writeUid(svcreqp->uid);
AsnEndStruct(aip, MSG_SVC_REQUEST_uid);
AsnStartStruct(aip, MSG_SVC_REQUEST_request);
writeRequest(svcreqp->request);
AsnEndStruct(aip, MSG_SVC_REQUEST_request);
value.intvalue = (Int4) svcreqp->platform;
AsnWrite(aip, MSG_SVC_REQUEST_platform, &value);
if (svcreqp->applId != NULL)
{
value.ptrvalue = (Pointer) svcreqp->applId;
AsnWrite(aip, MSG_SVC_REQUEST_appl_id, &value);
}
if (svcreqp->desKey != NULL)
{
value.ptrvalue = (Pointer) svcreqp->desKey;
AsnWrite(aip, MSG_SVC_REQUEST_des_key, &value);
}
if (svcreqp->wantPreResponse)
{
value.boolvalue = svcreqp->wantPreResponse;
AsnWrite(aip, SVC_REQUEST_want_pre_response, &value);
}
if (svcreqp->server_ip != 0)
{
value.intvalue = svcreqp->server_ip;
AsnWrite(aip, MSG_SVC_REQUEST_server_ip, &value);
}
AsnEndStruct(aip, MESSAGE_svc_request);
} /* writeSVC_REQUEST */
/********************************* SVC_RESPONSE *******************************/
NISvcRespPtr
NI_MakeMsgSvcresp(void)
{
NISvcRespPtr sp;
sp = (NISvcRespPtr) MemNew(sizeof(NISvcResp));
sp->seqno = 0;
sp->request = NI_MakeRequest();
return sp;
} /* NI_MakeMsgSvcresp() */
Int2
NI_DestroyMsgSvcresp(NISvcRespPtr sp)
{
if (sp == NULL)
return 1;
if (sp->request != NULL)
NI_DestroyRequest(sp->request);
MemFree(sp);
return 0;
} /* NI_DestroyMsgSvcresp() */
static NISvcRespPtr
readSVC_RESPONSE(void)
{
DataVal value;
NISvcRespPtr svcrespp;
svcrespp = NI_MakeMsgSvcresp();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_RESPONSE_seqno */
goto SvcRespFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcRespFail;
svcrespp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_RESPONSE_request */
goto SvcRespFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcRespFail;
if (readRequest(svcrespp->request) < 0)
goto SvcRespFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_SVC_RESPONSE_request */
goto SvcRespFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto SvcRespFail;
if (atp != MESSAGE_svc_response)
goto SvcRespFail;
return svcrespp;
SvcRespFail:
NI_DestroyMsgSvcresp(svcrespp);
return NULL;
} /* readSVC_RESPONSE */
static void
writeSVC_RESPONSE(NISvcRespPtr svcrespp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_svc_response);
value.intvalue = (Int4) svcrespp->seqno;
AsnWrite(aip, MSG_SVC_RESPONSE_seqno, &value);
AsnStartStruct(aip, MSG_SVC_RESPONSE_request);
writeRequest(svcrespp->request);
AsnEndStruct(aip, MSG_SVC_RESPONSE_request);
AsnEndStruct(aip, MESSAGE_svc_response);
} /* writeSVC_RESPONSE */
/************************************ COMMAND *********************************/
NICmdPtr
NI_MakeMsgCmd(void)
{
NICmdPtr cp;
cp = (NICmdPtr) MemNew(sizeof(NICmd));
cp->seqno = 0;
return cp;
} /* NI_MakeMsgCmd() */
Int2
NI_DestroyMsgCmd(NICmdPtr cp)
{
if (cp == NULL)
return 1;
MemFree(cp);
return 0;
} /* NI_DestroyMsgCmd() */
static NICmdPtr
readCOMMAND(void)
{
DataVal value;
NICmdPtr cmdp;
cmdp = NI_MakeMsgCmd();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* seqno */
goto CmdFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto CmdFail;
cmdp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* command */
goto CmdFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto CmdFail;
cmdp->code = (MsgCommand) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_command)
goto CmdFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto CmdFail;
return cmdp;
CmdFail:
NI_DestroyMsgCmd(cmdp);
return NULL;
} /* readCOMMAND */
static void
writeCOMMAND(NICmdPtr cmdp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_command);
value.intvalue = (Int4) cmdp->seqno;
AsnWrite(aip, MSG_CMD_seqno, &value);
value.intvalue = (Int4) cmdp->code;
AsnWrite(aip, MSG_CMD_command, &value);
AsnEndStruct(aip, MESSAGE_command);
} /* writeCOMMAND */
/************************************ PRE-RESPONSE *********************************/
NIPreRespPtr
NI_MakeMsgPreResp(void)
{
NIPreRespPtr cp;
cp = (NIPreRespPtr) MemNew(sizeof(NIPreResp));
cp->seqno = 0;
return cp;
} /* NI_MakeMsgPreResp() */
Int2
NI_DestroyMsgPreResp(NIPreRespPtr cp)
{
if (cp == NULL)
return 1;
MemFree(cp);
return 0;
} /* NI_DestroyMsgPreResp() */
static NIPreRespPtr
readPRE_RESPONSE(void)
{
DataVal value;
NIPreRespPtr prp;
prp = NI_MakeMsgPreResp();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* seqno */
goto PrFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto PrFail;
prp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* server IP */
goto PrFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto PrFail;
prp->server_ip = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_svc_pre_response)
goto PrFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto PrFail;
return prp;
PrFail:
NI_DestroyMsgPreResp(prp);
return NULL;
} /* readPRE_RESPONSE */
static void
writePRE_RESPONSE(NIPreRespPtr prp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_svc_pre_response);
value.intvalue = (Int4) prp->seqno;
AsnWrite(aip, MSG_SVC_PRE_RESPONSE_seqno, &value);
value.intvalue = (Int4) prp->server_ip;
AsnWrite(aip, MSG_SVC_PRE_RESPONSE_server_ip, &value);
AsnEndStruct(aip, MESSAGE_svc_pre_response);
} /* writePRE_RESPONSE */
/************************************ ACCT ************************************/
NIAcctPtr
NI_MakeMsgAcct(void)
{
NIAcctPtr ap;
ap = (NIAcctPtr) MemNew(sizeof(NIAcct));
ap->seqno = 0;
ap->jobname = NULL;
return ap;
} /* NI_MakeMsgAcct() */
Int2
NI_DestroyMsgAcct(NIAcctPtr ap)
{
if (ap == NULL)
return 1;
if (ap->jobname != NULL)
MemFree(ap->jobname);
MemFree(ap);
return 0;
} /* NI_DestroyMsgAcct() */
static NIAcctPtr
readACCT(void)
{
DataVal value;
NIAcctPtr accp;
accp = NI_MakeMsgAcct();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* seqno */
goto AcctFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AcctFail;
accp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* conid */
goto AcctFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AcctFail;
accp->conid = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* jobname */
goto AcctFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AcctFail;
accp->jobname = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* usertime */
goto AcctFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AcctFail;
accp->usertime = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* systemtime */
goto AcctFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AcctFail;
accp->systemtime = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_acct)
goto AcctFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto AcctFail;
return accp;
AcctFail:
NI_DestroyMsgAcct(accp);
return NULL;
} /* NIreadACCT */
static void
writeACCT(NIAcctPtr accp)
{
DataVal value;
AsnStartStruct(aip, MESSAGE_acct);
value.intvalue = (Int4) accp->seqno;
AsnWrite(aip, MSG_ACCT_seqno, &value);
value.intvalue = (Int4) accp->conid;
AsnWrite(aip, MSG_ACCT_conid, &value);
value.ptrvalue = (Pointer) accp->jobname;
AsnWrite(aip, MSG_ACCT_jobname, &value);
value.intvalue = (Int4) accp->usertime;
AsnWrite(aip, MSG_ACCT_usertime, &value);
value.intvalue = (Int4) accp->systemtime;
AsnWrite(aip, MSG_ACCT_systemtime, &value);
AsnEndStruct(aip, MESSAGE_acct);
} /* NIwriteACCT */
/************************************ CATALOG *********************************/
NICatalogPtr
NI_MakeMsgCatalog(void)
{
NICatalogPtr cp;
cp = (NICatalogPtr) MemNew(sizeof(NICatalog));
cp->motd = NULL;
cp->toolsetL = NULL;
return cp;
} /* NI_MakeCatalog */
Int2
NI_DestroyMsgCatalog(NICatalogPtr cp)
{
NodePtr np;
if (cp == NULL)
return 1;
if (cp->motd != NULL)
MemFree(cp->motd);
if ((np = cp->toolsetL) != NULL) {
do {
NI_DestroyToolset((NIToolsetPtr) np->elem);
np = ListDelete(np);
} while (np != NULL);
}
MemFree(cp);
return 0;
} /* NI_DestroyMsgCatalog */
static NICatalogPtr
readCATALOG(void)
{
DataVal value;
NICatalogPtr catp;
NIToolsetPtr tsp;
catp = NI_MakeMsgCatalog();
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* MSG_CATALOG_seqno */
goto CatalogFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto CatalogFail;
catp->seqno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto CatalogFail;
if (atp == MSG_CATALOG_motd) { /* MSG_CATALOG_motd ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto CatalogFail;
catp->motd = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto CatalogFail;
}
if (atp == MSG_CATALOG_toollists) { /* MSG_CATALOG_toollists ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto CatalogFail;
while ((atp = AsnReadId(aip, amp, atp)) == MSG_CATALOG_toollists_E) {
if (AsnReadVal(aip, atp, &value) < 0)
goto CatalogFail;
tsp = NI_MakeToolset();
if (readToolset(tsp) < 0)
goto CatalogFail;
ListBreakRing(tsp->services);
ListBreakRing(tsp->resources);
catp->toolsetL = ListInsert((VoidPtr) tsp, catp->toolsetL); /* end of list */
}
if (atp == NULL)
goto CatalogFail;
catp->toolsetL = catp->toolsetL->next; /* point to first */
if (AsnReadVal(aip, atp, &value) < 0) /* MSG_CATALOG_toollists */
goto CatalogFail;
ListBreakRing(catp->toolsetL);
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto CatalogFail;
}
if (atp != MESSAGE_catalog)
goto CatalogFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto CatalogFail;
return catp;
CatalogFail:
NI_DestroyMsgCatalog(catp);
return NULL;
} /* readCATALOG */
static void
writeCATALOG(NICatalogPtr catp)
{
DataVal value;
NodePtr np, lastnode;
AsnStartStruct(aip, MESSAGE_catalog);
value.intvalue = (Int4) catp->seqno;
AsnWrite(aip, MSG_CATALOG_seqno, &value);
if (catp->motd != NULL) {
value.ptrvalue = (Pointer) catp->motd;
AsnWrite(aip, MSG_CATALOG_motd, &value);
}
np = catp->toolsetL;
if (np != NULL) {
AsnStartStruct(aip, MSG_CATALOG_toollists);
lastnode = np->last;
while (np != NULL) {
AsnStartStruct(aip, MSG_CATALOG_toollists_E);
writeToolset((NIToolsetPtr) np->elem);
AsnEndStruct(aip, MSG_CATALOG_toollists_E);
if (np == lastnode)
break;
np = np->next;
}
AsnEndStruct(aip, MSG_CATALOG_toollists);
}
AsnEndStruct(aip, MESSAGE_catalog);
} /* writeCatalog */
/************************************ REQUEST *********************************/
ReqPtr
NI_MakeRequest(void)
{
ReqPtr rp;
rp = (ReqPtr) MemNew(sizeof(Request));
rp->clientAddr = NULL;
rp->clientPort = 0;
rp->service = NI_MakeService();
rp->resourceL = NULL;
return(rp);
} /* NI_MakeRequest() */
Int2
NI_DestroyRequest(ReqPtr rp)
{
if (rp == NULL)
return 1;
if (rp->clientAddr != NULL)
MemFree(rp->clientAddr);
if (rp->service != NULL)
NI_DestroyService(rp->service);
if (rp->resourceL != NULL) { /* destroy list of nodes and resources they point to */
while (rp->resourceL != NULL) {
NI_DestroyResource((NIResPtr)rp->resourceL->elem);
rp->resourceL = ListDelete(rp->resourceL);
}
}
MemFree(rp);
return 0;
} /* NI_DestroyRequest() */
static int
readRequest(ReqPtr reqp)
{
DataVal value;
NIResPtr resp;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto RequestFail;
if (atp == REQUEST_address) { /* REQUEST_address ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto RequestFail;
reqp->clientAddr = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto RequestFail;
}
if (atp == REQUEST_port) { /* REQUEST_port ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto RequestFail;
reqp->clientPort = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto RequestFail;
}
if (AsnReadVal(aip, atp, &value) < 0) /* REQUEST_svcentry */
goto RequestFail;
if (readService(reqp->service) < 0)
goto RequestFail;
if ((atp = AsnReadId(aip, amp, atp)) == REQUEST_resentry) {
if (AsnReadVal(aip, atp, &value) < 0)
goto RequestFail;
while ((atp = AsnReadId(aip, amp, atp)) == REQUEST_resentry_E) {
if (AsnReadVal(aip, atp, &value) < 0)
goto RequestFail;
resp = NI_MakeResource();
if (readResource(resp) < 0) {
NI_DestroyResource(resp);
goto RequestFail;
}
reqp->resourceL = ListInsert((VoidPtr) resp, reqp->resourceL); /* end of list */
}
if (atp == NULL)
goto RequestFail;
reqp->resourceL = reqp->resourceL->next; /* point to first */
if (AsnReadVal(aip, atp, &value) < 0) /* REQUEST_resentry */
goto RequestFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto RequestFail;
}
if (atp == NULL)
goto RequestFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto RequestFail;
return 0;
RequestFail:
if (reqp->resourceL != NULL) { /* destroy list of nodes and resources they point to */
while (reqp->resourceL != NULL) {
NI_DestroyResource((NIResPtr)reqp->resourceL->elem);
reqp->resourceL = ListDelete(reqp->resourceL);
}
}
return -1;
} /* readrequest */
static void
writeRequest(ReqPtr reqp)
{
DataVal value;
NodePtr np, lastnode;
if (reqp->clientAddr != NULL) {
value.ptrvalue = (Pointer) reqp->clientAddr;
AsnWrite(aip, REQUEST_address, &value);
}
if (reqp->clientPort != 0) {
value.intvalue = (Int4) reqp->clientPort;
AsnWrite(aip, REQUEST_port, &value);
}
AsnStartStruct(aip, REQUEST_svcentry);
writeService(reqp->service);
AsnEndStruct(aip, REQUEST_svcentry);
np = reqp->resourceL;
if (np != NULL) {
AsnStartStruct(aip, REQUEST_resentry);
lastnode = np->last;
while (np != NULL) {
AsnStartStruct(aip, REQUEST_resentry_E);
writeResource((NIResPtr) np->elem);
AsnEndStruct(aip, REQUEST_resentry_E);
if (np == lastnode)
break;
np = np->next;
}
AsnEndStruct(aip, REQUEST_resentry);
}
} /* writeRequest */
/************************************ UID *************************************/
NI_UidPtr
NI_MakeUid(void)
{
NI_UidPtr up;
up = (NI_UidPtr) MemNew(sizeof(NI_Uid));
up->username = NULL;
up->group = NULL;
up->domain = NULL;
return up;
} /* NI_MakeUid */
Int2
NI_DestroyUid(NI_UidPtr up)
{
if (up == NULL)
return 1;
if (up->username != NULL)
MemFree(up->username);
if (up->group != NULL)
MemFree(up->group);
if (up->domain != NULL)
MemFree(up->domain);
MemFree(up);
return 0;
} /* NI_DestroyUid */
static int
readUid(NI_UidPtr uidptr)
{
DataVal value;
if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != IDENTITY_username) /* username */
goto UidFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto UidFail;
uidptr->username = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* group ? */
goto UidFail;
if (atp == IDENTITY_group) {
if (AsnReadVal(aip, atp, &value) < 0)
goto UidFail;
uidptr->group = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* domain ? */
goto UidFail;
}
if (atp == IDENTITY_domain) {
if (AsnReadVal(aip, atp, &value) < 0)
goto UidFail;
uidptr->domain = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto UidFail;
}
if (AsnReadVal(aip, atp, &value) < 0)
goto UidFail;
return 0;
UidFail:
return -1;
} /* readUid */
static void
writeUid(NI_UidPtr uidptr)
{
DataVal value;
value.ptrvalue = (Pointer) uidptr->username;
AsnWrite(aip, IDENTITY_username, &value);
if (uidptr->group != NULL) {
value.ptrvalue = (Pointer) uidptr->group;
AsnWrite(aip, IDENTITY_group, &value);
}
if (uidptr->domain != NULL) {
value.ptrvalue = (Pointer) uidptr->domain;
AsnWrite(aip, IDENTITY_domain, &value);
}
} /* writeUid */
/************************************ SERVICE *********************************/
NISvcPtr
NI_MakeService(void)
{
NISvcPtr sp;
sp = (NISvcPtr) MemNew(sizeof(NIService));
sp->name = NULL;
sp->minVersion = 0;
sp->maxVersion = 0;
sp->id = 0;
sp->priority = 0;
sp->priorityTimeout = 0;
sp->priorityPenalty = 0;
sp->group = NULL;
sp->descrip = NULL;
sp->typeL = NULL;
sp->encryptionSupported = FALSE;
sp->trackingPeriod = 0;
sp->trackingCount = 0;
return sp;
} /* NI_MakeService() */
Int2
NI_DestroyService(NISvcPtr sp)
{
if (sp == NULL)
return 1;
if (sp->name != NULL)
MemFree(sp->name);
if (sp->group != NULL)
MemFree(sp->group);
if (sp->descrip != NULL)
MemFree(sp->descrip);
if (sp->typeL != NULL) { /* destroy list of service types */
ListStrDel(sp->typeL);
}
if (sp->subSetList != NULL) {
ListStrDel(sp->subSetList);
}
if (sp->superSetList != NULL) {
ListStrDel(sp->superSetList);
}
MemFree(sp);
return 0;
} /* NI_DestroyService() */
static int
readService(NISvcPtr svcptr)
{
DataVal value;
CharPtr svctype;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* SVC_ENTRY_name */
goto ServiceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->name = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* SVC_ENTRY_minvers */
goto ServiceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->minVersion = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* SVC_ENTRY_maxvers */
goto ServiceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->maxVersion = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
if (atp == SVC_ENTRY_id) { /* SVC_ENTRY_id ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->id = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_priority) { /* SVC_ENTRY_priority ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->priority = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_group) { /* SVC_ENTRY_group ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->group = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_description) { /* SVC_ENTRY_description ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->descrip = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_types) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
/* read the list of service types */
while ((atp = AsnReadId(aip, amp, atp)) == SVC_ENTRY_types_E)
{
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svctype = value.ptrvalue;
svcptr->typeL = ListInsert((VoidPtr) svctype, svcptr->typeL);
}
if (atp == NULL)
goto ServiceFail;
svcptr->typeL = svcptr->typeL->next; /* point to first */
if (AsnReadVal(aip, atp, &value) < 0) /* SVC_ENTRY_types */
goto ServiceFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_priority_timeout) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->priorityTimeout = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_priority_penalty) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->priorityPenalty = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_encryption_supported) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->encryptionSupported = value.boolvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_tracking_period) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->trackingPeriod = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == SVC_ENTRY_tracking_count) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
svcptr->trackingCount = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ServiceFail;
}
if (atp == NULL)
goto ServiceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ServiceFail;
return 0;
ServiceFail:
return -1;
} /* readService */
static void
writeService(NISvcPtr svcptr)
{
DataVal value;
NodePtr np;
NodePtr lastnode;
value.ptrvalue = (Pointer) svcptr->name;
AsnWrite(aip, SVC_ENTRY_name, &value);
value.intvalue = (Int4) svcptr->minVersion;
AsnWrite(aip, SVC_ENTRY_minvers, &value);
value.intvalue = (Int4) svcptr->maxVersion;
AsnWrite(aip, SVC_ENTRY_maxvers, &value);
if (svcptr->id != 0) {
value.intvalue = (Int4) svcptr->id;
AsnWrite(aip, SVC_ENTRY_id, &value);
}
if (svcptr->priority != 0) {
value.intvalue = (Int4) svcptr->priority;
AsnWrite(aip, SVC_ENTRY_priority, &value);
}
if (svcptr->group != NULL) {
value.ptrvalue = (Pointer) svcptr->group;
AsnWrite(aip, SVC_ENTRY_group, &value);
}
if (svcptr->descrip != NULL) {
value.ptrvalue = (Pointer) svcptr->descrip;
AsnWrite(aip, SVC_ENTRY_description, &value);
}
np = svcptr->typeL;
if (np != NULL) {
AsnStartStruct(aip, SVC_ENTRY_types);
lastnode = np->last;
while (np != NULL) {
value.ptrvalue = (Pointer) np->elem;
AsnWrite(aip, SVC_ENTRY_types_E, &value);
if (np == lastnode)
break;
np = np->next;
}
AsnEndStruct(aip, SVC_ENTRY_types);
}
if (svcptr->priorityTimeout != 0)
{
value.intvalue = svcptr->priorityTimeout;
AsnWrite(aip, SVC_ENTRY_priority_timeout, &value);
}
if (svcptr->priorityPenalty != 0)
{
value.intvalue = svcptr->priorityPenalty;
AsnWrite(aip, SVC_ENTRY_priority_penalty, &value);
}
if (svcptr->encryptionSupported)
{
value.boolvalue = svcptr->encryptionSupported;
AsnWrite(aip, SVC_ENTRY_encryption_supported, &value);
}
if (svcptr->trackingPeriod != 0)
{
value.intvalue = svcptr->trackingPeriod;
AsnWrite(aip, SVC_ENTRY_tracking_period, &value);
}
if (svcptr->trackingCount != 0)
{
value.intvalue = svcptr->trackingCount;
AsnWrite(aip, SVC_ENTRY_tracking_count, &value);
}
} /* writeService */
/************************************ RESOURCE ********************************/
NIResPtr
NI_MakeResource(void)
{
NIResPtr rp;
rp = (NIResPtr) MemNew(sizeof(NIResource));
rp->name = NULL;
rp->type = NULL;
rp->minVersion = 0;
rp->maxVersion = 0;
rp->id = 0;
rp->group = NULL;
rp->descrip = NULL;
return rp;
} /* NI_MakeResource() */
Int2
NI_DestroyResource(NIResPtr rp)
{
if (rp == NULL)
return 1;
if (rp->name != NULL)
MemFree(rp->name);
if (rp->type != NULL)
MemFree(rp->type);
if (rp->group != NULL)
MemFree(rp->group);
if (rp->descrip != NULL)
MemFree(rp->descrip);
MemFree(rp);
return 0;
} /* NI_DestroyResource */
static int
readResource(NIResPtr resptr)
{
DataVal value;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* RES_ENTRY_name */
goto ResourceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
resptr->name = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* RES_ENTRY_type */
goto ResourceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
resptr->type = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* RES_ENTRY_minvers */
goto ResourceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
resptr->minVersion = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* RES_ENTRY_maxvers */
goto ResourceFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
resptr->maxVersion = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ResourceFail;
if (atp == RES_ENTRY_id) { /* RES_ENTRY_id */
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
resptr->id = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ResourceFail;
}
if (atp == RES_ENTRY_group) { /* RES_ENTRY_group */
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
resptr->group = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ResourceFail;
}
if (atp == RES_ENTRY_description) { /* RES_ENTRY_description */
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
resptr->descrip = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ResourceFail;
}
if (AsnReadVal(aip, atp, &value) < 0)
goto ResourceFail;
return 0;
ResourceFail:
return -1;
} /* readResource */
static void
writeResource(NIResPtr resptr)
{
DataVal value;
value.ptrvalue = (Pointer) resptr->name;
AsnWrite(aip, RES_ENTRY_name, &value);
value.ptrvalue = (Pointer) resptr->type;
AsnWrite(aip, RES_ENTRY_type, &value);
value.intvalue = (Int4) resptr->minVersion;
AsnWrite(aip, RES_ENTRY_minvers, &value);
value.intvalue = (Int4) resptr->maxVersion;
AsnWrite(aip, RES_ENTRY_maxvers, &value);
if (resptr->id != 0) {
value.intvalue = (Int4) resptr->id;
AsnWrite(aip, RES_ENTRY_id, &value);
}
if (resptr->group != NULL) {
value.ptrvalue = (Pointer) resptr->group;
AsnWrite(aip, RES_ENTRY_group, &value);
}
if (resptr->descrip != NULL) {
value.ptrvalue = (Pointer) resptr->descrip;
AsnWrite(aip, RES_ENTRY_description, &value);
}
} /* writeResource */
/************************************ REGION *********************************/
NIRegionPtr
NI_MakeRegion(void)
{
NIRegionPtr rp;
rp = (NIRegionPtr) MemNew(sizeof(NIRegion));
rp->regionName = NULL;
rp->priorityDelta = 0;
return rp;
} /* NI_MakeRegion() */
Int2
NI_DestroyRegion(NIRegionPtr rp)
{
if (rp == NULL)
return 1;
if (rp->regionName != NULL)
MemFree(rp->regionName);
MemFree(rp);
return 0;
} /* NI_DestroyRegion() */
static int
readRegion(NIRegionPtr regptr)
{
DataVal value;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* REGION_DESCR_region_name */
goto RegionFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto RegionFail;
regptr->regionName = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* REGION_DESCR_priority_delta */
goto RegionFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto RegionFail;
regptr->priorityDelta = (Uint2) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto RegionFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto RegionFail;
return 0;
RegionFail:
return -1;
} /* readRegion */
static void
writeRegion(NIRegionPtr regptr)
{
DataVal value;
value.ptrvalue = (Pointer) regptr->regionName;
AsnWrite(aip, REGION_DESCR_region_name, &value);
value.intvalue = (Int4) regptr->priorityDelta;
AsnWrite(aip, REGION_DESCR_priority_delta, &value);
} /* writeRegion */
/************************************ PubKey ********************************/
NIPubKeyPtr
NI_MakePubKey(void)
{
NIPubKeyPtr pubkey;
pubkey = (NIPubKeyPtr) MemNew(sizeof(NIPubKey));
pubkey->bits = 0;
pubkey->modulus = NULL;
pubkey->exponent = NULL;
return pubkey;
} /* NI_MakePubKey */
Int2
NI_DestroyPubKey(NIPubKeyPtr pubkey)
{
if (pubkey == NULL)
return 1;
if (pubkey->modulus != NULL)
BSFree (pubkey->modulus);
if (pubkey->exponent != NULL)
BSFree (pubkey->exponent);
MemFree(pubkey);
return 0;
}
static int
readPubKey(NIPubKeyPtr pubkey)
{
DataVal value;
if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != RSA_PUBKEY_bits)
goto PubKeyFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto PubKeyFail;
pubkey->bits = (Int2) value.intvalue;
/* modulus */
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto PubKeyFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto PubKeyFail;
pubkey->modulus = (ByteStorePtr) value.ptrvalue;
/* exponent */
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto PubKeyFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto PubKeyFail;
pubkey->exponent = (ByteStorePtr) value.ptrvalue;
/* end struct */
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto PubKeyFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto PubKeyFail;
return 0;
PubKeyFail:
return -1;
}
static void
writePubKey(NIPubKeyPtr pubkey)
{
DataVal value;
if (pubkey == NULL)
return;
value.intvalue = pubkey->bits;
AsnWrite(aip, RSA_PUBKEY_bits, &value);
value.ptrvalue = pubkey->modulus;
AsnWrite(aip, RSA_PUBKEY_modulus, &value);
value.ptrvalue = pubkey->exponent;
AsnWrite(aip, RSA_PUBKEY_exponent, &value);
}
int
NI_ReadPubKey(AsnIoPtr extaip, AsnTypePtr extatp, NIPubKeyPtr pubkey)
{
AsnIoPtr savaip = aip;
AsnTypePtr savatp = atp;
DataVal value;
int retval = -1;
if (! InitMsg())
return 0;
aip = extaip;
atp = extatp;
if ((atp = AsnReadId(aip, amp, atp)) == RSA_PUBKEY)
{
if (AsnReadVal(aip, atp, &value) >= 0)
{
retval = readPubKey(pubkey);
}
}
aip = savaip;
atp = savatp;
return retval;
}
void
NI_WritePubKey(AsnIoPtr extaip, AsnTypePtr extatp, NIPubKeyPtr pubkey)
{
AsnIoPtr savaip = aip;
AsnTypePtr savatp = atp;
if (! InitMsg())
return;
aip = extaip;
atp = extatp;
if (extatp != NULL)
AsnStartStruct(extaip, extatp);
writePubKey(pubkey);
if (extatp != NULL)
AsnEndStruct(extaip, extatp);
aip = savaip;
atp = savatp;
}
/************************************ DispInfo ********************************/
NIDispInfoPtr
NI_MakeDispInfo(void)
{
NIDispInfoPtr dip;
dip = (NIDispInfoPtr) MemNew(sizeof(NIDispInfo));
dip->serialno = -1;
dip->isalternatelist = FALSE;
dip->numdispatchers = 0;
dip->displist = NULL;
dip->pubKey = NULL;
return dip;
} /* NI_MakeDispInfo */
Int2
NI_DestroyDispInfo(NIDispInfoPtr dip)
{
Int2 num;
if (dip == NULL)
return 1;
if (dip->displist != NULL)
{
for (num = 0; num < dip->numdispatchers; num++)
{
dip->displist[num] = (CharPtr) MemFree(dip->displist[num]);
}
MemFree(dip->displist);
}
if (dip->pubKey != NULL)
{
NI_DestroyPubKey(dip->pubKey);
}
MemFree(dip);
return 0;
} /* NI_DestroyDispInfo */
static int
readDispInfo(NIDispInfoPtr dip)
{
DataVal value;
int num;
if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != DISPATCHER_INFO_serial_no)
goto DispInfoFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto DispInfoFail;
dip->serialno = value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* is altlist?*/
goto DispInfoFail;
if (atp == INFO_is_alternate_list) {
if (AsnReadVal(aip, atp, &value) < 0)
goto DispInfoFail;
dip->isalternatelist = value.boolvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* num disps ?*/
goto DispInfoFail;
}
if (atp == DISPATCHER_INFO_num_dispatchers) {
if (AsnReadVal(aip, atp, &value) < 0)
goto DispInfoFail;
dip->numdispatchers = (int) value.intvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* disps ? */
goto DispInfoFail;
}
if (atp == DISPATCHER_INFO_disp_list) {
if (AsnReadVal(aip, atp, &value) < 0)
goto DispInfoFail;
dip->displist = (CharPtr PNTR) MemNew(sizeof(CharPtr) * dip->numdispatchers);
atp = AsnReadId(aip, amp, atp);
for (num = 0; num < dip->numdispatchers &&
atp == DISPATCHER_INFO_disp_list_E; num++)
{
if (AsnReadVal(aip, atp, &value) <= 0)
goto DispInfoFail;
dip->displist[num] = (CharPtr) value.ptrvalue;
atp = AsnReadId(aip, amp, atp);
}
if (AsnReadVal(aip, atp, &value) <= 0)
goto DispInfoFail;
atp = AsnReadId(aip, amp, atp);
}
if (atp == DISPATCHER_INFO_pub_key) {
if (AsnReadVal(aip, atp, &value) < 0)
goto DispInfoFail;
dip->pubKey = NI_MakePubKey();
if (readPubKey(dip->pubKey) < 0)
goto DispInfoFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto DispInfoFail;
}
if (AsnReadVal(aip, atp, &value) < 0)
goto DispInfoFail;
return 0;
DispInfoFail:
return -1;
} /* readDispInfo */
static void
writeDispInfo(NIDispInfoPtr dip)
{
DataVal value;
int num;
if (dip == NULL)
return;
value.intvalue = dip->serialno;
AsnWrite(aip, DISPATCHER_INFO_serial_no, &value);
value.boolvalue = dip->isalternatelist;
AsnWrite(aip, INFO_is_alternate_list, &value);
value.intvalue = dip->numdispatchers;
AsnWrite(aip, DISPATCHER_INFO_num_dispatchers, &value);
if (dip->displist != NULL) {
AsnStartStruct (aip, DISPATCHER_INFO_disp_list);
for (num = 0; num < dip->numdispatchers; num++) {
value.ptrvalue = dip->displist[num];
AsnWrite (aip, DISPATCHER_INFO_disp_list_E, &value);
}
AsnEndStruct (aip, DISPATCHER_INFO_disp_list);
}
if (dip->pubKey != NULL) {
AsnStartStruct (aip, DISPATCHER_INFO_pub_key);
writePubKey (dip->pubKey);
AsnEndStruct (aip, DISPATCHER_INFO_pub_key);
}
} /* writeDispInfo */
int
NI_ReadDispInfo(AsnIoPtr extaip, AsnTypePtr extatp, NIDispInfoPtr dip)
{
AsnIoPtr savaip = aip;
AsnTypePtr savatp = atp;
DataVal value;
int retval = -1;
if (! InitMsg())
return 0;
aip = extaip;
atp = extatp;
if ((atp = AsnReadId(aip, amp, atp)) == DISPATCHER_INFO)
{
if (AsnReadVal(aip, atp, &value) >= 0)
{
retval = readDispInfo(dip);
}
}
aip = savaip;
atp = savatp;
return retval;
}
void
NI_WriteDispInfo(AsnIoPtr extaip, AsnTypePtr extatp, NIDispInfoPtr dip)
{
AsnIoPtr savaip = aip;
AsnTypePtr savatp = atp;
if (! InitMsg())
return;
aip = extaip;
atp = extatp;
if (extatp != NULL)
AsnStartStruct(extaip, extatp);
writeDispInfo(dip);
if (extatp != NULL)
AsnEndStruct(extaip, extatp);
aip = savaip;
atp = savatp;
}
/************************************ TOOLSET *********************************/
NIToolsetPtr
NI_MakeToolset(void)
{
NIToolsetPtr tsp;
tsp = (NIToolsetPtr) MemNew(sizeof(NIToolset));
tsp->host = NULL;
tsp->motd = NULL;
tsp->services = NULL;
tsp->resources = NULL;
tsp->regions = NULL;
return tsp;
} /* NI_MakeToolset */
Int2
NI_DestroyToolset(NIToolsetPtr tsp)
{
NodePtr np;
if (tsp == NULL)
return 1;
if (tsp->host != NULL)
MemFree(tsp->host);
if (tsp->motd != NULL)
MemFree(tsp->motd);
if ((np = tsp->services) != NULL) {
do {
NI_DestroyService((NISvcPtr)np->elem);
np = ListDelete(np);
} while (np != NULL);
}
if ((np = tsp->resources) != NULL) {
do {
NI_DestroyResource((NIResPtr)np->elem);
np = ListDelete(np);
} while (np != NULL);
}
if ((np = tsp->regions) != NULL) {
do {
NI_DestroyRegion((NIRegionPtr)np->elem);
np = ListDelete(np);
} while (np != NULL);
}
MemFree(tsp);
return 0;
} /* NI_DestroyToolset */
NIToolsetPtr
NI_GetCatToolset(NIToolsetPtr tsp)
{
NIToolsetPtr dtsp;
NISvcPtr svcp, tsvcp;
NIResPtr resp, tresp;
NodePtr np;
dtsp = NI_MakeToolset();
if (tsp->host != NULL)
dtsp->host = StringSave(tsp->host);
if (tsp->motd != NULL)
dtsp->motd = StringSave(tsp->motd);
if (tsp->services != NULL) {
np = tsp->services->last;
do {
np = ListGetNext(np);
svcp = (NISvcPtr) np->elem;
/* note that services which are a "subset" of another listed */
/* service are filtered-out here */
if (svcp != NULL && svcp->subSetList == NULL) {
tsvcp = NI_MakeService();
if (svcp->name != NULL)
tsvcp->name = StringSave(svcp->name);
if (svcp->typeL != NULL)
{ /* make a copy of the list */
tsvcp->typeL = ListStrCopy(svcp->typeL);
}
tsvcp->minVersion = svcp->minVersion;
tsvcp->maxVersion = svcp->maxVersion;
tsvcp->priority = svcp->priority;
tsvcp->id = 0; /* these two not sent in catalog */
tsvcp->group = NULL;
if (svcp->descrip != NULL)
tsvcp->descrip = StringSave(svcp->descrip);
dtsp->services = ListInsert((VoidPtr) tsvcp, dtsp->services);
}
} while (np != tsp->services->last);
if (dtsp->services != NULL)
{
dtsp->services = dtsp->services->next; /* point to first */
}
}
if (tsp->resources != NULL) {
np = tsp->resources->last;
do {
np = ListGetNext(np);
resp = (NIResPtr) np->elem;
if (resp != NULL) {
tresp = NI_MakeResource();
if (resp->name != NULL)
tresp->name = StringSave(resp->name);
if (resp->type != NULL)
tresp->type = StringSave(resp->type);
tresp->minVersion = resp->minVersion;
tresp->maxVersion = resp->maxVersion;
tresp->id = 0; /* these two not sent in catalog */
tresp->group = NULL;
if (resp->descrip != NULL)
tresp->descrip = StringSave(resp->descrip);
dtsp->resources = ListInsert((VoidPtr) tresp, dtsp->resources);
}
} while (np != tsp->resources->last);
if (dtsp->resources != NULL)
{
dtsp->resources = dtsp->resources->next; /* point to first */
}
}
return dtsp;
} /* NI_GetCatToolset */
static int
readToolset(NIToolsetPtr tsp)
{
DataVal value;
NISvcPtr svcp;
NIResPtr resp;
NIRegionPtr reg;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* TOOLSET_host */
goto ToolsetFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
tsp->host = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ToolsetFail;
if (atp == TOOLSET_motd) { /* TOOLSET_motd ? */
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
tsp->motd = (CharPtr) value.ptrvalue;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ToolsetFail;
}
if (atp == TOOLSET_services) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_services_E) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
svcp = NI_MakeService();
readService(svcp);
tsp->services = ListInsert((VoidPtr) svcp, tsp->services);
}
if (atp == NULL)
goto ToolsetFail;
tsp->services = tsp->services->next; /* point to first */
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ToolsetFail;
}
if (atp == TOOLSET_resources) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_resources_E) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
resp = NI_MakeResource();
readResource(resp);
tsp->resources = ListInsert((VoidPtr) resp, tsp->resources);
}
if (atp == NULL)
goto ToolsetFail;
tsp->resources = tsp->resources->next; /* point to first */
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ToolsetFail;
}
if (atp == TOOLSET_regions) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_regions_E) {
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
reg = NI_MakeRegion();
readRegion(reg);
tsp->regions = ListInsert((VoidPtr) reg, tsp->regions);
}
if (atp == NULL)
goto ToolsetFail;
tsp->regions = tsp->regions->next; /* point to first */
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL)
goto ToolsetFail;
}
if (AsnReadVal(aip, atp, &value) < 0)
goto ToolsetFail;
return 0;
ToolsetFail:
return -1;
} /* readToolset */
static void
writeToolset(NIToolsetPtr tsp)
{
DataVal value;
NodePtr np, lastnode;
if (tsp->host != NULL)
value.ptrvalue = (Pointer) tsp->host;
else
value.ptrvalue = (Pointer) StringSave("N/A");
AsnWrite(aip, TOOLSET_host, &value);
if (tsp->motd != NULL) {
value.ptrvalue = (Pointer) tsp->motd;
AsnWrite(aip, TOOLSET_motd, &value);
}
np = tsp->services;
if (np != NULL) {
AsnStartStruct(aip, TOOLSET_services);
lastnode = np->last;
while (np != NULL) {
AsnStartStruct(aip, TOOLSET_services_E);
writeService((NISvcPtr) np->elem);
AsnEndStruct(aip, TOOLSET_services_E);
if (np == lastnode)
break;
np = np->next;
}
AsnEndStruct(aip, TOOLSET_services);
}
np = tsp->resources;
if (np != NULL) {
AsnStartStruct(aip, TOOLSET_resources);
lastnode = np->last;
while (np != NULL) {
AsnStartStruct(aip, TOOLSET_resources_E);
writeResource((NIResPtr) np->elem);
AsnEndStruct(aip, TOOLSET_resources_E);
if (np == lastnode)
break;
np = np->next;
}
AsnEndStruct(aip, TOOLSET_resources);
}
np = tsp->regions;
if (np != NULL) {
AsnStartStruct(aip, TOOLSET_regions);
lastnode = np->last;
while (np != NULL) {
AsnStartStruct(aip, TOOLSET_regions_E);
writeRegion((NIRegionPtr) np->elem);
AsnEndStruct(aip, TOOLSET_regions_E);
if (np == lastnode)
break;
np = np->next;
}
AsnEndStruct(aip, TOOLSET_regions);
}
} /* writeToolset */
/******************************************************************************/
/* */
/* Message and Handle Functions */
/* */
/******************************************************************************/
/*
* Purpose: "High level" message read for ASN.1 messages
*
* Parameters:
* hp "Message handle", describing parameters of input environment
* unblocked Flag indicating whether input should "block" if unable
* to read a complete message
*
* Returns:
* NULL, if unable to read a message ... if hp->have_blocked is
* set, then this reflects an inability to read a complete
* message at this time
* a pointer to the message which was just read, otherwise
*
*
* Description:
* Try to read a message from the socket specified by the hp
* data structure. A message must begin with the "MESSAGE"
* identifier, followed by the type of the message. Once the
* type of the message has been determined, the remainder of
* the message is read using the corresponding readXXX()
* function.
*
* Matters are more complex when the "unblocked" parameter
* is TRUE. In this case, if a failure occurs on a message read,
* an attempt is made to see whether any bytes of data were
* read from the socket upon this invocation. If so, the
* have_blocked flag is set for the caller, and AsnIoReset() is
* called to deal with a future attempt to read from this socket
* when more data becomes available.
*
* Note:
* This is the highest level read function which should be
* called by an application program. All the other "static"
* functions called here should not be called directly by an
* application program.
*
* The ASN.1 error handling is performing using the setjmp()/
* longjmp() paradigm, where a function can return to an earlier
* context if an error occurs.
*
* Currently, it is not possible to distinguish
* between an ASN.1 format error, and an ASN failure due to
* inability to read the requested quantity of data. For this
* reason, if the "unblocked" option is selected, it will take
* hp->r_timeout seconds to detect either of these
* conditions. In the best of all possible worlds, it would
* be possible to distinguish between "data not YET available"
* and "invalid data" conditions.
*/
NIMsgPtr
MsgRead(MHandPtr hp, Boolean unblocked)
{
DataVal value;
NIMsgPtr mp = NULL;
int start_byte_count = hp->num_queued_bytes;
NodePtr timer = NULL;
ni_errno = NIE_MSGREAD;
hp->unblocked_mode = unblocked;
hp->have_blocked = FALSE;
/* for unblocked I/O, set a "hangup" timeout which can be detected at */
/* at later time, if we are unable to read a complete or valid message */
if (unblocked && hp->readTimeoutHook != NULL)
timer = NI_SetTimer(time(NULL) + hp->r_timeout, hp->readTimeoutHook,
(VoidPtr) hp);
hp->readTimer = timer;
if (hp->longjump == TRUE) {
if (SetJump(ni_env)) {
/* return from LongJump (error handler) */
goto MsgReadFail;
}
}
StringCpy(ni_errtext, "AsnReadId or AsnReadVal returned bad value");
aip = hp->raip;
atp = MESSAGE;
if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE) /* Must read a MESSAGE */
goto MsgReadFail; /* don't have to read val as Null return is always fatal to channel */
if (AsnReadVal(aip, atp, &value) < 0)
goto MsgReadFail;
if ((atp = AsnReadId(aip, amp, atp)) == NULL) /* type of message */
goto MsgReadFail;
if (AsnReadVal(aip, atp, &value) < 0)
goto MsgReadFail;
mp = (NIMsgPtr) MemNew(sizeof(NIMessage));
mp->conid = hp->conid;
mp->type = NI_UNKNOWN;
if (atp == MESSAGE_ack) {
if ((mp->msun.ack = readACK()) != NULL)
mp->type = NI_ACK;
goto gotmessage;
}
if (atp == MESSAGE_nack) {
if ((mp->msun.nack = readNACK()) != NULL)
mp->type = NI_NACK;
goto gotmessage;
}
if (atp == MESSAGE_login) {
if ((mp->msun.login = readLOGIN()) != NULL)
mp->type = NI_LOGIN;
goto gotmessage;
}
if (atp == MESSAGE_svc_list) {
if ((mp->msun.svclist = readSVC_LIST()) != NULL)
mp->type = NI_SVC_LIST;
goto gotmessage;
}
if (atp == MESSAGE_svc_request) {
if ((mp->msun.svcreq = readSVC_REQUEST()) != NULL)
mp->type = NI_SVC_REQUEST;
goto gotmessage;
}
if (atp == MESSAGE_svc_response) {
if ((mp->msun.svcresp = readSVC_RESPONSE()) != NULL)
mp->type = NI_SVC_RESPONSE;
goto gotmessage;
}
if (atp == MESSAGE_command) {
if ((mp->msun.command = readCOMMAND()) != NULL)
mp->type = NI_COMMAND;
goto gotmessage;
}
if (atp == MESSAGE_svc_pre_response) {
if ((mp->msun.preresp = readPRE_RESPONSE()) != NULL)
mp->type = NI_SVC_PRE_RESPONSE;
goto gotmessage;
}
if (atp == MESSAGE_acct) {
if ((mp->msun.acct = readACCT()) != NULL)
mp->type = NI_ACCT;
goto gotmessage;
}
if (atp == MESSAGE_catalog) {
if ((mp->msun.catalog = readCATALOG()) != NULL)
mp->type = NI_CATALOG;
goto gotmessage;
}
gotmessage:
if (mp->type == NI_UNKNOWN) {
StringCpy(ni_errtext, "unknown msg type");
goto MsgReadFail;
}
else { /* got good stuff */
MsgFreeSavedData(hp); /* free associated data */
hp->unblocked_mode = FALSE;
hp->have_blocked = FALSE;
NI_CancelTimer (hp->readTimer);
hp->readTimer = NULL;
return mp;
}
MsgReadFail:
if (mp != NULL)
MsgDestroy(mp);
/* if ( things didn't go well, but there was more data read from the */
/* socket ) then */
if (start_byte_count < hp->num_queued_bytes)
hp->have_blocked = TRUE; /* set things up to try again */
if (hp->have_blocked)
{ /* failed due to data unavailability */
hp->cur_index = 0; /* reset queued read pointer */
AsnIoReset (aip); /* reset ASN input stream */
/* caller should try again later, based upon detecting hp->have_blocked */
}
hp->unblocked_mode = FALSE;
return NULL;
} /* MsgRead */
/*
* Purpose: "High level" message write for ASN.1 messages
*
* Parameters:
* hp "Message handle", describing parameters of I/O environment
* mp Message to be written
* noDestroy If set, refrain from destroying the message
*
* Returns:
* -1, if unable to write the message
* 0, otherwise
*
*
* Description:
* Try to write a message from the socket specified by the hp
* data structure. The writing of the message is performed
* using the writeXXX() function which corresponds to the type
* of the message to be written.
*/
Int2
MsgWrite(MHandPtr hp, NIMsgPtr mp, Boolean noDestroy)
{
DataVal value;
ni_errno = NIE_MSGWRITE;
if (hp->longjump == TRUE) {
if (SetJump(ni_env)) {
/* return from LongJump (error handler) */
if (! noDestroy)
MsgDestroy(mp); /* failing, so destroy it */
return -1;
}
}
aip = hp->waip;
AsnWrite(aip, MESSAGE, &value);
switch (mp->type) {
case NI_ACK:
writeACK(mp->msun.ack);
break;
case NI_NACK:
writeNACK(mp->msun.nack);
break;
case NI_LOGIN:
writeLOGIN(mp->msun.login);
break;
case NI_SVC_LIST:
writeSVC_LIST(mp->msun.svclist);
break;
case NI_SVC_REQUEST:
writeSVC_REQUEST(mp->msun.svcreq);
break;
case NI_SVC_RESPONSE:
writeSVC_RESPONSE(mp->msun.svcresp);
break;
case NI_COMMAND:
writeCOMMAND(mp->msun.command);
break;
case NI_SVC_PRE_RESPONSE:
writePRE_RESPONSE(mp->msun.preresp);
break;
case NI_ACCT:
writeACCT(mp->msun.acct);
break;
case NI_CATALOG:
writeCATALOG(mp->msun.catalog);
break;
default:
ni_errno = NIE_MSGUNK;
StringCpy(ni_errtext, "unable to write msg");
if (! noDestroy)
MsgDestroy(mp);
return -1;
}
AsnIoFlush(aip);
if (! noDestroy)
MsgDestroy(mp);
return 0;
} /* MsgWrite */
/*
* Purpose: Build a message of the specified type, populating it with
* a pointer to the actual message data, and the connection ID.
*
* Parameters:
* type The type of message to be built
* conn Connection ID associated with this session
* stp Pointer to the actual message data
*
* Returns:
* NULL, if unable to allocate memory for the message, or if
* the specified message type is invalid
* a pointer to the newly-build message, otherwise
*
*
* Description:
* Create a message data structure, and populate it as indicated.
*/
NIMsgPtr
MsgBuild(MsgType type, Uint4 conn, VoidPtr stp)
{
NIMsgPtr mp;
if (! InitMsg())
return NULL;
mp = (NIMsgPtr) MemNew(sizeof(NIMessage));
if (mp == NULL)
return NULL;
mp->type = type;
mp->conid = conn;
switch (mp->type) {
case NI_ACK:
mp->msun.ack = (NIAckPtr) stp;
break;
case NI_NACK:
mp->msun.nack = (NINackPtr) stp;
break;
case NI_LOGIN:
mp->msun.login = (NILoginPtr) stp;
break;
case NI_SVC_LIST:
mp->msun.svclist = (NISvcListPtr) stp;
break;
case NI_SVC_REQUEST:
mp->msun.svcreq = (NISvcReqPtr) stp;
break;
case NI_SVC_RESPONSE:
mp->msun.svcresp = (NISvcRespPtr) stp;
break;
case NI_COMMAND:
mp->msun.command = (NICmdPtr) stp;
break;
case NI_SVC_PRE_RESPONSE:
mp->msun.preresp = (NIPreRespPtr) stp;
break;
case NI_ACCT:
mp->msun.acct = (NIAcctPtr) stp;
break;
case NI_CATALOG:
mp->msun.catalog = (NICatalogPtr) stp;
break;
default:
ni_errno = NIE_MSGUNK;
StringCpy(ni_errtext, "unable to build");
MemFree (mp);
return NULL;
}
return mp;
} /* MsgBuild */
/*
* Purpose: Destroy the specified message
*
* Parameters:
* mp A pointer to the message structure to be destroyed
*
* Returns:
* -1, if the specified pointer is NULL, or if the message
* is of an unknown type
* 0, otherwise
*
*
* Description:
* Destroy the specified message, using the appropriate message
* destructor function.
*/
Int2
MsgDestroy(NIMsgPtr mp)
{
if (mp == NULL)
return -1;
switch (mp->type) {
case NI_ACK:
NI_DestroyMsgAck(mp->msun.ack);
break;
case NI_NACK:
NI_DestroyMsgNack(mp->msun.nack);
break;
case NI_LOGIN:
NI_DestroyMsgLogin(mp->msun.login);
break;
case NI_SVC_LIST:
NI_DestroyMsgSvclist(mp->msun.svclist);
break;
case NI_SVC_REQUEST:
NI_DestroyMsgSvcreq(mp->msun.svcreq);
break;
case NI_SVC_RESPONSE:
NI_DestroyMsgSvcresp(mp->msun.svcresp);
break;
case NI_COMMAND:
NI_DestroyMsgCmd(mp->msun.command);
break;
case NI_SVC_PRE_RESPONSE:
NI_DestroyMsgPreResp(mp->msun.preresp);
break;
case NI_ACCT:
NI_DestroyMsgAcct(mp->msun.acct);
break;
case NI_CATALOG:
NI_DestroyMsgCatalog(mp->msun.catalog);
break;
default:
ni_errno = NIE_MSGUNK;
StringCpy(ni_errtext, "unable to destroy msg");
MemFree(mp);
return -1;
}
MemFree(mp);
return 0;
} /* MsgDestroy */
/*
* Purpose: Create a message handle
*
* Returns:
* NULL, if unable to allocate the required memory, open
* a socket, set the socket to non-blocking mode, or
* initialize the ASN.1 I/O streams successfully
* a pointer to the new message handle, otherwise
*
*
* Description:
* Create a "message" handle, which is the basic unit of message
* I/O. A message handle includes, among other things, a logical
* connection ID, a socket used for both input and output, ASN.1
* I/O stream pointers, and a queue of input data which has
* already been read from the socket, but has not yet been
* processed successfully using ASN.1.
*
* Note:
* This is currently the only place where conid is incremented,
* and therefore, the only place where conid is written to the
* Conid file.
*/
MHandPtr
MsgMakeHandle(Boolean createSocket)
{
MHandPtr mh;
if (! InitMsg()) {
StringCpy(ni_errtext, "Network services ASN.1 initialization failed");
ni_errno = NIE_ASN1SPECFAIL;
return NULL;
}
if ((mh = (MHandPtr) MemNew(sizeof(MHandle))) == NULL) {
StringCpy(ni_errtext, "unable to allocate new memory");
return NULL;
}
mh->hostname = NULL;
mh->conid = conid++;
WriteConFile(conid);
mh->seqno = 1;
mh->sok = -1;
if (createSocket) {
if ((mh->sok = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) ==
INVALID_SOCKET) {
#ifdef NETP_INET_NEWT
SOCK_ERRNO = ABS(mh->sok);
#endif
StringCpy(ni_errtext, sys_errlist[SOCK_INDEX_ERRNO]);
MemFree(mh);
return NULL;
}
LOG_SOCKET(mh->sok, TRUE);
if (NI_SETNONBLOCKING(mh->sok) == -1) {
StringCpy(ni_errtext, sys_errlist[SOCK_INDEX_ERRNO]);
MemFree(mh);
return NULL;
}
}
mh->r_timeout = NI_READ_TIMEOUT;
mh->w_timeout = NI_WRITE_TIMEOUT;
mh->state = NI_CREATED;
mh->extra_proc_info = NULL;
mh->read_filter = NULL;
mh->write_filter = NULL;
mh->write_filt_pass_thru = TRUE;
mh->read_filt_pass_thru = TRUE;
mh->readTimeoutHook = NULL;
mh->writeTimeoutHook = NULL;
mh->readTimer = NULL;
mh->writeTimer = NULL;
mh->encryption = NULL;
mh->isBrokered = FALSE;
mh->brokeredPort = 0;
mh->peer = 0;
if ((mh->raip = AsnIoNew((ASNIO_BIN | ASNIO_IN), (FILE *) NULL, (Pointer) mh, NI_AsnRead, NI_AsnWrite)) == NULL) {
LOG_SOCKET(mh->sok, FALSE);
NI_CLOSESOCKET(mh->sok);
StringCpy(ni_errtext, "unable to allocate new AsnIoPtr (raip)");
MemFree(mh);
return NULL;
}
if ((mh->waip = AsnIoNew((ASNIO_BIN | ASNIO_OUT), (FILE *) NULL, (Pointer) mh, NI_AsnRead, NI_AsnWrite)) == NULL) {
AsnIoClose(mh->raip);
LOG_SOCKET(mh->sok, FALSE);
NI_CLOSESOCKET(mh->sok);
StringCpy(ni_errtext, "unable to allocate new AsnIoPtr (waip)");
MemFree(mh);
return NULL;
}
AsnIoSetBufsize(mh->waip, NI_BLOCKSIZE);
mh->longjump = FALSE;
mh->access_time = time(NULL);
mh->have_blocked = FALSE;
mh->num_queued_bytes = 0;
mh->cur_index = 0;
mh->queued_data_list = NULL;
mh->unblocked_mode = FALSE;
return mh;
} /* MsgMakeHandle */
/*
* Purpose: Destroy the specified message handle
*
* Parameters:
* hp A pointer to the message handle to be destroyed
*
* Returns:
* -1, if the specified pointer is NULL
* 0, otherwise
*
*
* Description:
* Destroy the specified message handle, close its socket,
* close the ASN streams, and free any associated queued data.
*/
Int2
MsgDestroyHandle(MHandPtr hp)
{
if (hp == NULL)
return -1;
if (hp->sok != INVALID_SOCKET)
{
LOG_SOCKET(hp->sok, FALSE);
NI_CLOSESOCKET(hp->sok);
}
if (hp->hostname != NULL)
MemFree(hp->hostname);
NI_CancelTimer(hp->readTimer);
NI_CancelTimer(hp->writeTimer);
AsnIoClose(hp->raip);
AsnIoClose(hp->waip);
if (hp->encryption != NULL)
{
NI_DestroyEncrStruct(hp->encryption);
}
MsgFreeSavedData(hp);
MemFree(hp);
return 0;
} /* MsgDestroyHandle */
/*
* Purpose: Set "longjump" error mechanism
*
* Parameters:
* mh A pointer to the message handle for which the "longjump"
* error is to be set.
*
*
* Description:
* Set the ASN I/O error handler to be a function which will
* simply "longjump", and hence return control to the place at
* which setjmp() was last called. The "longjump" flag should
* be check by a setjmp() caller, prior to calling setjmp(), to
* assure that the error handling mechanism is in place.
*/
void
MsgSetLJError(MHandPtr mh)
{
AsnIoSetErrorMsg(mh->raip, NI_ASNIOError);
AsnIoSetErrorMsg(mh->waip, NI_ASNIOError);
mh->longjump = TRUE;
} /* MsgSetLJError */
/*
* Purpose: Set the "read" timeout for this message handle
*
* Parameters:
* mh A pointer to the message handle for which the read timeout
* is to be set.
*
*
* Description:
* Set the "read" timeout for this message handle. A default
* value is set-up at the time when the message handle is created.
*
* Note:
* This timeout is also used for the "hung" timeout.
*/
void
MsgSetReadTimeout(MHandPtr mh, int t)
{
mh->r_timeout = t;
} /* MsgSetReadTimeout */
/*
* Purpose: Set the "write" timeout for this message handle
*
* Parameters:
* mh A pointer to the message handle for which the write timeout
* is to be set.
*
*
* Description:
* Set the "write" timeout for this message handle. A default
* value is set-up at the time when the message handle is created.
*/
void
MsgSetWriteTimeout(MHandPtr mh, int t)
{
mh->w_timeout = t;
} /* MsgSetWriteTimeout */
/*
* Purpose: Set the filter parameters for this message handle
*
* Parameters:
* mh A pointer to the message handle for which the parameters
* are to be set.
*
* ex_proc A pointer to an optional user-defined data structure to be
* used by the read and write filters.
*
* wfilt A write filter function, which may be used, e.g., to collect
* statistics, or to compress the data to be written.
*
* rfilt A read filter function, which may be used, e.g., to collect
* statistics, or to decompress the data which was read.
*
* wfilt_pass Indicates whether wfilt needs to modify the data buffer (e.g.,
* this will be FALSE if doing statistics only, but TRUE if
* doing data compression).
*
* rfilt_pass Indicates whether rfilt needs to return a modified data
* buffer (e.g., this will be FALSE if doing statistics only,
* but TRUE if doing data decompression).
*
*
* Description:
* Set the I/O filters for this message handle. A default
* value (no filter) is set up at the time when the message
* handle is created.
*
* Note:
* It is the responsibility of the higher-level software (i.e.,
* not this module) to free any data associated with ex_proc.
*/
void
MsgSetFilters(MHandPtr mh, VoidPtr ex_proc, NI_WriteFilt wfilt,
NI_ReadFilt rfilt, Boolean wfilt_pass, Boolean rfilt_pass)
{
if (mh == NULL)
return;
mh->extra_proc_info = ex_proc;
mh->write_filter = wfilt;
mh->read_filter = rfilt;
mh->write_filt_pass_thru = wfilt_pass;
mh->read_filt_pass_thru = rfilt_pass;
}
/*
* Purpose: Set the timeout hooks for this message handle
*
* Parameters:
* mh A pointer to the message handle for which the parameters
* are to be set.
*
* rhook A hook to be called when the read timeout expires
*
* whook A hook to be called when the write timeout expires
*
*
* Description:
* Set the read and write timeout hooks for this message handle.
* A default value (no hook) is set up at the time when the
* message handle is created.
*
* Note:
* The write hook is currently usused (6/2/93).
*/
void
MsgSetTimeoutHooks(MHandPtr mh, NI_TimeoutHook rhook, NI_TimeoutHook whook)
{
if (mh == NULL)
return;
mh->readTimeoutHook = rhook;
mh->writeTimeoutHook = whook;
}
/*
* Purpose: Initialize the ASN.1 object loader for this module
*
* Parameters:
* none
*
*
* Description:
* Dynamically load the ASN.1 static header, if necessary.
*/
static Boolean
InitMsg (void)
{
static Boolean loaded = FALSE;
if (loaded)
return TRUE;
if (! AsnLoad())
return FALSE;
loaded = TRUE;
return TRUE;
}
/******************************************************************************/
/* */
/* Functions used by AsnTool for socket IO (readfunc and writefunc) */
/* */
/******************************************************************************/
/*
* Purpose: Read some data on behalf of the ASN.1 library
*
* Parameters:
* p A pointer to the message handle structure
* buf The buffer into which the data should be read
* len Maximum number of bytes to be read
*
* Returns:
* 0, if operating in "unblocked mode", and are unable to
* read the requested amount of data
* -ETIMEOUT, if blocked, waiting for data to be available, but
* none arrived before the read timeout expired
* -errno [ system error number ], for other errors
* the number of bytes read, otherwise
*
*
* Description:
* This is the 'readfunc' function used by ASN.1 to read some
* data from the specified ASN.1 I/O stream.
*
* First, try to read some data from the "queued data", i.e.,
* data which was read from the socket on a previous iteration,
* but ASN.1 processing failed because there was insufficient
* data.
*
* Subsequently, try to read from the socket. If the data is
* unavailable, and running in "blocked" mode, wait for either
* the data to appear or for the read timeout to expire.
*
* In the case where data is read successfully, store it in
* the "queued data" area.
*
* Once data has been read successfully, optionally post-process
* it through a filter routine. This routine may, e.g., collect
* statistics or provide a de-compression mechanism. If it is
* a de-compression mechanism, any data which would not fit in
* the original buffer is stored in the "queued data" area, to
* be re-read by the next call to this function.
*/
Int2 LIBCALLBACK
NI_AsnRead(Pointer p, CharPtr buf, Uint2 len)
{
MHandPtr mh;
int bytesread;
int ready;
time_t secs0, secs1;
fd_set rfds;
struct timeval timeout;
CharPtr extra_buf;
Int4 extra_buf_len;
CharPtr extra_encr_buf;
Int4 extra_encr_buf_len;
NI_NetServHook activityHook;
mh = (MHandPtr) p;
/* always provide caller with queued data, if available */
if (MsgHaveSavedData(mh))
{
return MsgReadSavedData(mh, buf, len);
}
mh->access_time = time(NULL);
DisabVibrant();
while ((bytesread = NI_READSOCKET(mh->sok, buf, len)) <= 0) {
#ifndef NETP_INET_PCNFS
if (bytesread == 0) {
break;
}
#else
SOCK_ERRNO = tk_geterrno (mh->sok);
#endif
#ifdef NETP_INET_NEWT
SOCK_ERRNO = ABS(bytesread);
#endif
switch (SOCK_ERRNO) {
case EINTR:
continue;
case EAGAIN:
#if EAGAIN != EWOULDBLOCK
case EWOULDBLOCK:
#endif /* EAGAIN != EWOULDBLOCK */
if (mh->unblocked_mode)
{
mh->have_blocked = TRUE;
EnabVibrant();
return 0;
}
FD_ZERO(&rfds);
FD_SET(mh->sok, &rfds);
secs0 = secs1 = time(NULL);
RepeatSelect:
/* a simple poll is effected when timeout.tv_sec == 0 */
timeout.tv_sec = mh->r_timeout - (secs1 - secs0);
timeout.tv_usec = 0;
ready = NI_select(mh->sok + 1, &rfds, NULL, NULL, &timeout);
if (ready > 0)
continue;
if (ready == 0)
{
EnabVibrant();
return (-ABS(ETIMEDOUT));
}
switch (SOCK_ERRNO) {
case EINTR:
/* update the timeout because select() does not */
secs1 = time(NULL);
if (secs1 - secs0 > (time_t) mh->r_timeout)
secs1 = secs0 + mh->r_timeout;
goto RepeatSelect;
default:
break;
}
EnabVibrant();
return (-ABS(SOCK_ERRNO));
default:
EnabVibrant();
return (-ABS(SOCK_ERRNO));
}
#ifdef WIN16
#ifdef NETP_INET_WSOCK
{
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
#else
Yield();
#endif
#endif
}
EnabVibrant();
extra_buf = NULL;
extra_encr_buf = NULL;
if (mh->read_filter != NULL)
{
if (mh->read_filt_pass_thru)
{
mh->read_filter (mh, buf, bytesread, len, NULL, NULL);
}
else {
bytesread = (int) mh->read_filter (mh, buf, bytesread, len,
&extra_buf, &extra_buf_len);
}
}
if (mh->encryption != NULL && mh->encryption->read_filter != NULL)
{
bytesread = (int) mh->encryption->read_filter (mh, buf, bytesread,
len, &extra_encr_buf,
&extra_encr_buf_len);
}
if ((activityHook = NI_ActivityHook()) != NULL)
{
activityHook (mh, NetServHook_read, bytesread);
}
/* save what we just read */
MsgSaveData (mh, buf, bytesread);
if (extra_buf != NULL)
{ /* there was some extra data which we didn't get to read */
MsgSaveData (mh, extra_buf, (Uint2) extra_buf_len);
mh->cur_index -= extra_buf_len; /* enqueue data for next read */
MemFree (extra_buf);
extra_buf = NULL;
}
if (extra_encr_buf != NULL)
{ /* there was some extra encrypted data which we didn't get to read */
MsgSaveData (mh, extra_encr_buf, (Uint2) extra_encr_buf_len);
mh->cur_index -= extra_encr_buf_len; /* enqueue data for next read */
MemFree (extra_encr_buf);
extra_encr_buf = NULL;
}
return bytesread;
} /* NI_AsnRead */
/*
* Purpose: Write some data on behalf of the ASN.1 library
*
* Parameters:
* p A pointer to the message handle structure
* buf The buffer into which the data should be written
* len Number of bytes to be written
*
* Returns:
* -ETIMEOUT, if unable to write the data before the write
* timeout expired
* -errno [ system error number ], for other errors
* the number of bytes written, otherwise
*
*
* Description:
* This is the 'writefunc' function used by ASN.1 to write some
* data to the specified ASN.1 I/O stream.
*
* If unable to write the data immediately, block until it is
* possible to write the data, or until the write timeout expires.
*
* The data to be output is optionally passed through a filter
* routine. This routine may, for example, collect statistics
* or compress the data to be written.
*
* Note:
* It is relatively unlikely that "writing" will block, thus
* causing the calling application to block. For "writing" to
* block, there would need to be flow control imposed in the
* TCP/IP protocol suite, which is an unlikely occurance when
* passing small quantities of data.
*/
Int2 LIBCALLBACK
NI_AsnWrite(Pointer p, CharPtr buf, Uint2 len)
{
MHandPtr mh;
Int2 byteswrit, bytesleft;
int ready;
fd_set wfds;
time_t secs0, secs1 = 0;
struct timeval timeout;
CharPtr newbuf;
Uint2 newlen;
CharPtr tmpbuf = NULL;
NI_NetServHook activityHook;
mh = (MHandPtr) p;
mh->access_time = time(NULL);
newbuf = buf;
newlen = len;
if (mh->write_filter != NULL)
{
if (mh->write_filt_pass_thru)
{ /* write filter is "pass-through only" */
mh->write_filter (mh, buf, len, NULL);
}
else { /* write filter modifies buffer to be written */
tmpbuf = (CharPtr) MemNew(len + 5);
newlen = (Uint2) mh->write_filter(mh, buf, len, tmpbuf);
newbuf = tmpbuf;
}
}
if (mh->encryption != NULL && mh->encryption->write_filter != NULL)
{
tmpbuf = (CharPtr) MemNew(len + 9);
newlen = (Uint2) mh->encryption->write_filter(mh, newbuf, newlen, tmpbuf);
newbuf = tmpbuf;
}
if ((activityHook = NI_ActivityHook()) != NULL)
{
activityHook (mh, NetServHook_write, newlen);
}
DisabVibrant();
for (bytesleft = newlen; bytesleft > 0; bytesleft -= byteswrit,
newbuf += byteswrit) {
while ((byteswrit = NI_WRITESOCKET(mh->sok, newbuf, bytesleft)) <= 0) {
if (byteswrit == 0)
{
#ifdef NETP_INET_NEWT
/* this is a real kludge to deal with the fact that NEWT */
/* sometimes returns 0 on a send() for no good reason; we simulate*/
/* that we were told that the send() would block */
byteswrit = -EWOULDBLOCK;
#else
WriteCleanup(tmpbuf);
return 0;
#endif /* NETP_INET_NEWT */
}
#ifdef NETP_INET_NEWT
SOCK_ERRNO = ABS(byteswrit);
#endif
#ifdef NETP_INET_PCNFS
SOCK_ERRNO = tk_geterrno (mh->sok);
#endif
byteswrit = 0; /* don't allow byte count to become messed up */
switch (SOCK_ERRNO) {
case EINTR:
continue;
case EAGAIN:
#if EAGAIN != EWOULDBLOCK
case EWOULDBLOCK:
#endif
#ifdef NETP_INET_NEWT
/* work-around for bug in version 2.00 of NEWT; a select()*/
/* will never recognize when it's O.K. to write to a */
/* socket */
if (secs1 == 0)
{
secs1 = secs0 = time(NULL);
}
else {
secs1 = time(NULL);
if (secs1 - secs0 > (time_t) mh->w_timeout)
{
WriteCleanup(tmpbuf);
return (-ABS(ETIMEDOUT));
}
}
break;
#endif
FD_ZERO(&wfds);
FD_SET(mh->sok, &wfds);
secs0 = secs1 = time(NULL);
RepeatSelect:
/* a simple poll is effected when timeout.tv_sec == 0 */
timeout.tv_sec = mh->w_timeout - (secs1 - secs0);
timeout.tv_usec = 0;
ready = NI_select(mh->sok + 1, NULL, &wfds, NULL, &timeout);
if (ready > 0)
continue;
if (ready == 0)
{
WriteCleanup(tmpbuf);
return (-ABS(ETIMEDOUT));
}
switch (SOCK_ERRNO) {
case EINTR:
/* update the timeout because select() does not */
secs1 = time(NULL);
if (secs1 - secs0 > (time_t) mh->w_timeout)
secs1 = secs0 + mh->w_timeout;
goto RepeatSelect;
default:
break;
}
WriteCleanup(tmpbuf);
return (-ABS(SOCK_ERRNO));
default:
WriteCleanup(tmpbuf);
return (-ABS(SOCK_ERRNO));
}
#ifdef WIN16
#ifdef NETP_INET_WSOCK
{
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
#else
Yield();
#endif
#endif
}
}
WriteCleanup(tmpbuf);
return (Int2)len;
} /* NI_AsnWrite */
/*
* Purpose: Clean-up for NI_AsnWrite
*
* Parameters:
* tmpbuf Temporary buffer to be freed, if non-NULL
*
*
* Description:
* Frees temporary buffer, and re-enables Vibrant for user
* input. Used because there are so many return paths from
* NI_AsnWrite.
*
*/
static void
WriteCleanup (CharPtr tmpbuf)
{
if (tmpbuf != NULL)
{
MemFree (tmpbuf);
}
EnabVibrant();
}
/*
* Purpose: ASN.1 Error handling
*
* Parameters:
* level Error code to be returned
* str Error text generated by ASN.1
*
*
* Description:
* This is the error handling function used by ASN.1; it is called
* when any ASN.1 I/O error occurs.
*
* When an ASN.1 I/O error occurs, this function stores the
* error text in a safe place, and "longjumps", returning
* control to a point where setjmp() was last called. This point
* should occur in a relatively high-level function (above the
* ASN.1 library).
*
* Note:
* Due to the implementation of setjmp()/longjmp(), if level is
* 0, then the setjmp() caller will see the value 1; this
* mechanism is used to allow a setjmp() caller to distinguish
* between the case when they have just "set" the jump environment
* (return value == 0), and all other cases.
*/
void LIBCALLBACK
NI_ASNIOError(Int2 level, CharPtr str)
{
StringCpy(ni_errtext, str);
LongJump(ni_env, level);
} /* NI_ASNIOError */
#if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
/*
* Purpose: Implementation of blocked select() for use with NEWT and WSOCK
*
* Parameters:
* width "width" of file descriptor bits maps
* rfds Read file descriptor bit maps
* wfds Write file descriptor bit maps
* xfds Exception file descriptor bit maps
*
* Returns:
* 0, if the timeout period elapses
* -1, if an error occurred
* the number of available file descriptors (selected file
* descriptors which are available for processing), otherwise
*
*
* Description:
* Provide a "blocked" select() mechanism, because NEWT does
* not provide one.
*
* Note:
* When calling select(), the width of the file descriptor
* maps is increased by one, to handle an off-by-one error
* associated with the NEWT library.
*
* This function is used in WinSock (rather than WinSock's
* select function) to ensure that message removal/dispatching
* is done in a manner which does not interfere with scrollbar
* management.
*/
int
NI_poll_select(int width, fd_set PNTR rfds, fd_set PNTR wfds, fd_set PNTR xfds, struct timeval PNTR timeout)
{
fd_set trfds, twfds, txfds;
int rdy;
time_t t_end;
struct timeval tmout;
if (rfds != NULL)
Nlm_MemCopy(&trfds, rfds, sizeof(trfds));
if (wfds != NULL)
Nlm_MemCopy(&twfds, wfds, sizeof(twfds));
if (xfds != NULL)
Nlm_MemCopy(&txfds, xfds, sizeof(txfds));
t_end = timeout->tv_sec + Nlm_GetSecs();
tmout.tv_sec = 0;
tmout.tv_usec = 0;
#ifdef NETP_INET_WSOCK
width--;
#endif
while (Nlm_GetSecs() < t_end) {
if (rfds != NULL)
Nlm_MemCopy(rfds, &trfds, sizeof(trfds));
if (wfds != NULL)
Nlm_MemCopy(wfds, &twfds, sizeof(twfds));
if (xfds != NULL)
Nlm_MemCopy(xfds, &txfds, sizeof(txfds));
#ifdef NETP_INET_WSOCK
{
MSG msg;
Boolean done = FALSE;
/* get all the available messages, avoiding WM_LBUTTONUP since */
/* this will cause scroll bars to hang, for some unknown reason */
while (! done)
{
done = TRUE;
if (PeekMessage(&msg, NULL, 0, WM_LBUTTONUP-1, PM_REMOVE))
{
done = FALSE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (PeekMessage(&msg, NULL, WM_LBUTTONUP+1, 0xffff, PM_REMOVE))
{
done = FALSE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
#else
#ifdef WIN16
Yield();
#endif
#endif
/* select with (width + 1) because NetManage boundary condition error */
if ((rdy = select((width + 1), rfds, wfds, xfds, &tmout)) != 0) {
if (rdy < 0) { /* error */
#ifdef NETP_INET_NEWT
errno = ABS(rdy);
#endif
rdy = -1;
}
return rdy;
}
}
return 0; /* timed out */
} /* NI_poll_select */
#endif
#ifdef NI_BLOCK_WITH_FUNCTION
/*
* Purpose: Implementation of setting non-blocked-socket mode for platforms
* for which it is difficult to perform this functionality within
* a macro.
*
* Parameters:
* fd Socket file descriptor
*
*/
int
NI_SetNonBlocking (int fd)
{
int mode = 1;
#ifdef NETP_INET_WSOCK
u_long lmode = 1;
return ioctlsocket (fd, FIONBIO, &lmode);
#endif
#ifdef NETP_INET_PCNFS
return tk_ioctl (fd, FIONBIO, &mode);
#endif
#ifdef NETP_INET_TGV
return socket_ioctl (fd, FIONBIO, &mode);
#endif
#ifdef NETP_INET_WPW
long lmode = 0;
return ioctl (fd, FIONBIO, &mode);
#endif
#ifdef NETP_INET_TWG
/**************************************************************************/
/* WARNING: THIS IS CURRENTLY NOT IMPLEMENTED PROPERLY BECAUSE WE (W. */
/* GILBERT/J. EPSTEIN) ARE NOT ABLE TO MAKE NETWORK SERVICES */
/* OPERATE PROPERLY IN NON-BLOCKING MODE. AT SOME FUTURE DATE, */
/* THE REMAINDER OF NETWORK SERVICES SHOULD BE DEBUGGED AND THE */
/* FOLLOWING LINE SHOULD READ: lmode = 1 */
/* 17 June 1993 */
/**************************************************************************/
/*
long lmode = 0;
return ioctl (fd, FIONBIO, &lmode);
*/
return 0;
#endif
#ifdef NETP_INET_UCX
/**************************************************************************/
/* WARNING: THIS IS CURRENTLY UNIMPLEMENTED BECAUSE IT IS NOT CLEAR THAT */
/* IT IS POSSIBLE TO SPECIFY BLOCKING/NONBLOCKING MODE FOR UCX */
/* 22 June 1993 */
/**************************************************************************/
return 0;
#endif
}
/*
* Purpose: Implementation of setting blocked-socket mode for platforms
* for which it is difficult to perform this functionality within
* a macro.
*
* Parameters:
* fd Socket file descriptor
*
*/
int
NI_SetBlocking (int fd)
{
int mode = 0;
#ifdef NETP_INET_WSOCK
u_long lmode = 0;
return ioctlsocket (fd, FIONBIO, &lmode);
#endif
#ifdef NETP_INET_PCNFS
return tk_ioctl (fd, FIONBIO, &mode);
#endif
#ifdef NETP_INET_TGV
return socket_ioctl (fd, FIONBIO, &mode);
#endif
#ifdef NETP_INET_WPW
long lmode = 0;
return ioctl (fd, FIONBIO, &lmode);
#endif
#ifdef NETP_INET_TWG
/*
long lmode = 0;
return ioctl (fd, FIONBIO, &lmode);
*/
return 0;
#endif
#ifdef NETP_INET_UCX
/**************************************************************************/
/* WARNING: THIS IS CURRENTLY UNIMPLEMENTED BECAUSE IT IS NOT CLEAR THAT */
/* IT IS POSSIBLE TO SPECIFY BLOCKING/NONBLOCKING MODE FOR UCX */
/* 22 June 1993 */
/**************************************************************************/
return 0;
#endif
}
#endif /* BLOCK_WITH_FUNCTION */
/*
* Purpose: Test as to whether there's available data already enqueued
*
* Parameters:
* mh Pointer to "message handle" data structure
*
* Returns:
* FALSE, if there is no data already enqueued
* TRUE, otherwise
*
*
* Description:
* Determine whether there is currently enqueued data on a
* "message handle" data structure.
*/
static Boolean
MsgHaveSavedData(MHandPtr mh)
{
if (!mh->unblocked_mode)
return FALSE;
if (mh->queued_data_list == NULL)
return FALSE;
if (mh->num_queued_bytes <= 0)
return FALSE;
return (mh->cur_index < mh->num_queued_bytes);
}
/*
* Purpose: Read data which was previously stored in this "message handle"
*
* Parameters:
* mh Pointer to "message handle" data structure
* buf Buffer where data should be stored
* len Maximum number of bytes to read out
*
* Returns:
* the number of bytes read from the enqueued data list
*
*
* Description:
* Return up to len bytes of enqueued data, by traversing
* the enqueued data structure, beginning with the location
* where the "current byte" pointer is currently pointing.
*
* Note:
* The enqueued data is stored in a list of chained blocks, where
* at all times, all the blocks are full, except (possibly) the
* last block.
*/
#define MSG_READ_BLOCK_SIZE 1024
static int
MsgReadSavedData(MHandPtr mh, CharPtr buf, Uint2 len)
{
NodePtr startpt;
NodePtr blk;
int addl_queue_data;
int local_index;
int bytes_copied;
int data_in_this_block;
int bytes_to_copy;
if (mh->queued_data_list == NULL || len <= 0 || mh->num_queued_bytes == 0)
return 0;
blk = startpt = mh->queued_data_list;
addl_queue_data = mh->num_queued_bytes - mh->cur_index;
local_index = 0;
bytes_copied = 0;
/* traverse the portion of the list which is necessary to get past */
/* the current "file" pointer, and then copy up to len bytes of */
/* data from the remaining blocks */
do {
/* if ( this is the last block ) then */
if (mh->num_queued_bytes - local_index < MSG_READ_BLOCK_SIZE)
data_in_this_block = mh->num_queued_bytes % MSG_READ_BLOCK_SIZE;
else
data_in_this_block = MSG_READ_BLOCK_SIZE;
/* if ( there is more data to be skipped over ) then */
if (local_index < mh->cur_index)
{ /* there is more data to be skipped over */
if (local_index + data_in_this_block <= mh->cur_index)
{ /* skip this block */
local_index += data_in_this_block;
continue;
}
else { /* skip a portion of this block, and copy the remainder */
data_in_this_block -= (mh->cur_index - local_index);
local_index = mh->cur_index;
}
}
bytes_to_copy = MIN((int) len, data_in_this_block);
MemCopy(buf, blk->elem, bytes_to_copy);
buf += bytes_to_copy;
len -= bytes_to_copy;
bytes_copied += bytes_to_copy;
mh->cur_index += bytes_to_copy;
local_index += bytes_to_copy;
} while ( (blk = ListGetNext(blk)) != startpt && len > 0);
return bytes_copied;
}
/*
* Purpose: Store len bytes of data from a buffer, for future use
*
* Parameters:
* mh Pointer to "message handle" data structure
* buf Buffer of data to be copied
* len Number of bytes to save
*
*
* Description:
* Store len bytes of data at the end of a list of "enqueued data."
* After finding the current end of the queue, data is added
* to the final block (up to its capacity), and then, if needed,
* additional blocks are allocated to store the remaining data.
*/
static void
MsgSaveData(MHandPtr mh, CharPtr buf, Uint2 len)
{
NodePtr tail;
int bytes_to_copy;
int starting_byte;
CharPtr newdata;
if (len == 0 || !mh->unblocked_mode)
return;
/* get to the correct place in the list, and then start storing */
tail = mh->queued_data_list;
/* point to tail of list; in a ring, the element before the head is the */
/* tail */
if (tail != NULL)
tail = tail->last;
/* if ( more room in the current element ) then */
if ((starting_byte = mh->num_queued_bytes % MSG_READ_BLOCK_SIZE) != 0)
{
bytes_to_copy = MIN(MSG_READ_BLOCK_SIZE - starting_byte, (int) len);
newdata = (CharPtr) tail->elem;
MemCopy (&newdata[starting_byte], buf, bytes_to_copy);
len -= bytes_to_copy;
buf += len;
mh->num_queued_bytes += bytes_to_copy;
}
/* while ( there is more data to be copied ) */
while (len > 0)
{ /* create a new element, and copy data into that element */
newdata = MemNew(MSG_READ_BLOCK_SIZE);
bytes_to_copy = MIN(MSG_READ_BLOCK_SIZE, len);
MemCopy (newdata, buf, bytes_to_copy);
buf += bytes_to_copy;
len -= bytes_to_copy;
mh->num_queued_bytes += bytes_to_copy;
tail = ListInsert(newdata, tail);
}
mh->cur_index = mh->num_queued_bytes;
if (tail == NULL)
mh->queued_data_list = NULL;
else
mh->queued_data_list = tail->next;
}
/*
* Purpose: Free data associated with an "enqueued data list"
*
* Parameters:
* mh Pointer to "message handle" data structure
*
*
* Description:
* Free all the message elements associated with a list of
* enqueued data, and set other message handle elements to
* appropriate values such that software accessing those structures
* will not, erroneously, think that there is valid enqueued data
* in the structure.
*/
static void
MsgFreeSavedData (MHandPtr mh)
{
NodePtr np;
CharPtr elem;
mh->unblocked_mode = FALSE;
mh->have_blocked = FALSE;
mh->num_queued_bytes = 0;
mh->cur_index = 0;
np = mh->queued_data_list;
mh->queued_data_list = NULL;
while (np != NULL)
{
elem = (CharPtr) np->elem;
if (elem != NULL)
MemFree (elem);
np = ListDelete(np);
}
}
/*
* Purpose: Set and pop the hour-glass cursor
*
* Parameters:
* none
*
* Description:
* According to the NEWT/NetManage documentation, it is
* beneficial to make the cursor into an hourglass to block-out
* unwanted events during some socket calls.
*/
#if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
static HCURSOR saveCursor = NULL;
static void SetHourGlass(void)
{
#ifdef NETP_INET_NEWT
static HCURSOR hourCursor;
hourCursor = LoadCursor(NULL, IDC_WAIT);
saveCursor = SetCursor(hourCursor);
#endif
}
static void PopHourGlass(void)
{
#ifdef NETP_INET_NEWT
if (saveCursor != NULL)
SetCursor(saveCursor);
#endif
}
#endif /* NETP_INET_NEWT */